swagger: "2.0" info: description: | This is the REST API for [trashnothing.com](https://trashnothing.com). To learn more about the API or to register your app for use with the API visit the [trash nothing Developer page](https://trashnothing.com/developer). NOTE: All date-time values are [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) and are in [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601) (eg. 2019-02-03T01:23:53). version: "1.3" title: trash nothing termsOfService: > https://trashnothing.com/terms host: trashnothing.com basePath: /api/v1.3 security: - oauth2_implicit: - basic - oauth2_code: - basic tags: - name: users description: Retrieve and update user data. - name: posts description: Retrieve and update posts. - name: groups description: Search, subscribe and unsubscribe to groups. - name: photos description: Upload, delete and rotate photos. - name: messages description: > Manage conversations and messages with other users.

It's important to note that messages are always sent by email to the users. So it's possible to create a fully functional app using the trash nothing API without using any of the conversations or messages API endpoints. These API endpoints are useful for developers who want to build a complete messaging interface into their app. - name: stories description: Retrieve and submit stories. - name: misc description: Miscellaneous functionality. schemes: - https # # paths: /users/me: get: tags: - users summary: Retrieve current user operationId: get_current_user produces: - application/json responses: 200: description: User data schema: $ref: "#/definitions/CurrentUser" 404: description: User not found. put: tags: - users summary: Update current user operationId: update_current_user description: > Update the current user. All fields are optional so requests can update just one or multiple user properties at a time. consumes: - multipart/form-data produces: - application/json parameters: - name: firstname in: formData description: The first name of the user. required: false type: string maxLength: 64 - name: lastname in: formData description: The last name of the user. required: false type: string maxLength: 64 - name: public_name in: formData description: > Whether or not the users' first and last name will be visible to other users. Set to 1 to enable and 0 to disable. required: false type: integer - name: email_posts_frequency in: formData description: > How often new post email notifications are sent to the user. One of: weekly, twice_weekly, daily, 12_hours, 8_hours, 6_hours, 4_hours, 2_hours, hourly

To turn off new post email notifications, set this to an empty string. required: false type: string - name: digest_photos in: formData description: > Whether or not to include photos in the digest emails. Set to 1 to enable photos and 0 to disable photos. required: false type: integer - name: email_post_reminders in: formData description: If set to 1, the user will receive emails to remind them to handle their old posts. To disable, set to 0. required: false type: integer - name: password in: formData description: > A new password for the users' account. When setting a new password, the old_password parameter must be passed and set to the users' current password.

NOTE: The password and old_password properties can NOT be used when the user property has_password is false. Instead, use the password reset endpoint to have a new password emailed to the user. required: false type: string - name: old_password in: formData description: The users current password. This is required when the user is changing their password. required: false type: string - name: profile_image_source in: formData description: > The source of the users' profile image. The values this can be set to change dynamically based on the users' account. To get the values that can be used, use the source properties returned by the profile images endpoint. required: false type: string - name: last_listings_view in: formData description: The UTC date and time when the user last viewed the newest posts on the All Posts page. required: false type: string format: date-time - name: public_post_sources in: formData description: > A comma separated list of the sources to show public posts from. Currently only 'trashnothing' is supported. If not passed, all sources will be enabled. If set to an empty string, no sources will be enabled which effectively disables public posts for the user so that the user will only see posts from the groups they are a member of. Setting to an empty string is only allowed if the user is a member of one or more groups. required: false type: string - name: show_all_group_posts in: formData description: > Set to 1 to show all group posts on the main posts page and in the digests. Set to 0 to only show group posts in the area defined by the users' location. Can only be set to 0 if the users' location is already set. required: false type: integer - name: special_notices in: formData description: > Whether or not the user wants to receive special notice emails from the groups they are a member of. Special notices are admin posts that the group moderators choose to send out by email. Set to 1 to enable and 0 to disable. required: false type: integer - name: about_me in: formData description: A short bio a user has written about themselves to help other members get to know them better. required: false type: string maxLength: 4096 - name: email_search_alerts in: formData description: If set to 1, the user will receive emails when new posts that match one of their search alerts. To disable, set to 0. required: false type: integer - name: notify_about_reposts in: formData description: > If set to 1, the user will be notified about reposts. This affects digests and search alerts. If set to 0, the user will not be notified about reposts.

This does not affect the posts that are returned by the /posts endpoint which has an include_reposts option for this purpose.

See the repost_count field of post objects for details about how reposts are identified. required: false type: integer - name: email_message_delay in: formData description: > How quickly new messages from other users are emailed to this user. One of: immediate, 30_minutes, 1_hour, 2_hours, 4_hours, 6_hours, 8_hours
If set to anything other than immediate, the user will receive a digest email summarizing all of the new messages that they haven't viewed. required: false type: string - name: email_newsletters in: formData description: If set to 1, the user will receive occasional email newsletters from trash nothing. To disable, set to 0. required: false type: string responses: 200: description: The updated user data. schema: $ref: "#/definitions/CurrentUser" 400: description: Invalid parameter. /users/{user_id}: get: tags: - users summary: Retrieve a user operationId: get_user produces: - application/json parameters: - name: user_id in: path description: A user ID. required: true type: string responses: 200: description: User data schema: $ref: "#/definitions/User" 404: description: User not found. /users/{user_id}/display: get: tags: - users summary: Retrieve user display info description: > Retrieve a user and information related to the user (eg. recent posts) that is useful for displaying a more detailed view of the user. operationId: get_user_and_related_data produces: - application/json parameters: - name: user_id in: path description: A user ID. required: true type: string responses: 200: description: The user and related data. schema: type: object properties: user: $ref: "#/definitions/User" posts: type: array description: > Other active posts from the user in the last 90 days. A maximum of 30 posts will be returned. items: $ref: "#/definitions/Post" offer_count: type: integer description: Count of offer posts made by the user in the last 90 days. wanted_count: type: integer description: Count of wanted posts made by the user in the last 90 days. feedback: type: array description: Feedback the current user has left on the user. items: $ref: "#/definitions/Feedback" 404: description: User not found. /users/me/posts: get: tags: - users summary: List current users' posts description: > NOTE: In order to make it easier to see all a users' posts, the current users' location preferences are not applied when listing or searching posts from a single user. If location based filtering of the posts is needed, the latitude, longitude and radius parameters may be used. operationId: get_current_user_posts produces: - application/json parameters: - name: sort_by in: query description: > How to sort the posts that are returned. One of: date, active, distance

Date sorting will sort posts from newest to oldest. Active sorting will sort active posts before satisfied, withdrawn and expired posts and then sort by date. Distance sorting will sort the closest posts first. required: false default: date type: string - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, taken, wanted, received, admin required: true type: string - name: sources in: query description: > A comma separated list of the post sources to retrieve posts from. The available sources are: groups, trashnothing, open_archive_groups. The trashnothing source is for public posts that are posted on trash nothing but are not associated with any group. The open_archive_groups source provides a way to easily request posts from groups that have open_archives set to true without having to pass a group_ids parameter. When passed, it will automatically return posts from open archive groups that are within the area specified by the latitude, longitude and radius parameters (or the current users' location if latitude, longitude and radius aren't passed).

NOTE: For requests using an api key instead of oauth, passing the trashnothing source or the open_archive_groups source makes the latitude, longitude and radius parameters required. required: true type: string - name: group_ids in: query description: > A comma separated list of the group IDs to retrieve posts from. This parameter is only used if the 'groups' source is passed in the sources parameter and only groups that the current user is a member of or that are open archives groups will be used (the group IDs of other groups will be silently discarded*).

NOTE: For requests using an api key instead of oauth, this field is required if the 'groups' source is passed. In addition, only posts from groups that have open_archives set to true will be used (the group IDS of other groups will be silently discarded*).

*To determine which group IDs were used and which were discarded, use the group_ids field in the response. required: false default: The group IDs of every group the current user is a member of. type: string - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: latitude in: query description: > The latitude of a point around which to return posts. required: false type: number - name: longitude in: query description: > The longitude of a point around which to return posts. required: false type: number - name: radius in: query description: > The radius in meters of a circle centered at the point defined by the latitude and longitude parameters. When latitude, longitude and radius are passed, only posts within the circle defined by these parameters will be returned. required: false type: number minimum: 0 maximum: 257500 - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. required: false type: string format: date-time - name: date_max in: query description: Only posts older than this UTC date and time will be returned. required: false type: string format: date-time - name: outcomes in: query type: string required: false default: '' description: > A comma separated list of the post outcomes to return. The available post outcomes are: satisfied, withdrawn

There are also a couple special values that can be passed. If set to an empty string (the default), only posts that are not satisfied and not withdrawn and not expired are returned. If set to 'all', all posts will be returned no matter what outcome the posts have. If set to 'not-promised', only posts that are not satisfied ant not withdrawn and not expired and not promised are returned. # - name: user_state in: query type: string required: false default: '' description: > If user_state is set, only posts matching the state specified will be returned. Only one state may be passed and it must be one of the following: viewed, replied, bookmarked

NOTE: This option will only work with oauth requests. - name: include_reposts in: query description: > If set to 1 (the default), posts that are reposts will be included. If set to 0, reposts will be excluded. See the repost_count field of post objects for details about how reposts are identified. required: false default: 1 minimum: 0 maximum: 1 type: integer responses: 200: description: The posts and paging data. schema: type: object properties: posts: type: array items: $ref: "#/definitions/Post" num_posts: type: integer description: The total number of posts available. page: type: integer description: The page number of the posts being returned. per_page: type: integer description: The number of posts being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first post being returned (an integer between 1 and num_posts). end_index: type: integer description: The index of the last post being returned (an integer between start_index and num_posts). group_ids: type: array items: type: string description: > The IDs of the groups that the posts were retrieved from (will be null when no group IDs were used). These IDs may be a subset of the requested group IDs when a request includes group IDs for groups that are not open archives and that the current user is not a member of. If the open_archive_groups source is used, these IDs may include the IDs of open archive groups that weren't present in the group_ids parameter of the request. last_listings_view: type: string format: date-time description: > The UTC date and time when the current user last viewed the newest posts on the All Posts page (may be null).

NOTE: For this to be accurate, clients must update the last_listings_view property of the current user every time the user is shown the newest posts on the All Posts page.

NOTE: For requests using an api key instead of oauth, this field is always null. 400: description: Missing or invalid parameters. /users/{user_id}/posts: get: tags: - users summary: List posts by a user description: > NOTE: In order to make it easier to see all a users' posts, the current users' location preferences are not applied when listing or searching posts from a single user. If location based filtering of the posts is needed, the latitude, longitude and radius parameters may be used. operationId: get_user_posts produces: - application/json parameters: - name: user_id in: path description: > The user ID of the user whose posts will be retrieved. Using 'me' as the user_id will return the posts for the current user. required: true type: string - name: sort_by in: query description: > How to sort the posts that are returned. One of: date, active, distance

Date sorting will sort posts from newest to oldest. Active sorting will sort active posts before satisfied, withdrawn and expired posts and then sort by date. Distance sorting will sort the closest posts first. required: false default: date type: string - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, taken, wanted, received, admin required: true type: string - name: sources in: query description: > A comma separated list of the post sources to retrieve posts from. The available sources are: groups, trashnothing, open_archive_groups. The trashnothing source is for public posts that are posted on trash nothing but are not associated with any group. The open_archive_groups source provides a way to easily request posts from groups that have open_archives set to true without having to pass a group_ids parameter. When passed, it will automatically return posts from open archive groups that are within the area specified by the latitude, longitude and radius parameters (or all the open archive groups the requested user has posted to if latitude, longitude and radius aren't passed).

NOTE: For requests using an api key instead of oauth, passing the trashnothing source or the open_archive_groups source makes the latitude, longitude and radius parameters required. required: true type: string - name: group_ids in: query description: > A comma separated list of the group IDs to retrieve posts from. This parameter is only used if the 'groups' source is passed in the sources parameter and only groups that the current user is a member of or that are open archives groups will be used (the group IDs of other groups will be silently discarded*).

NOTE: For requests using an api key instead of oauth, this field is required if the 'groups' source is passed. In addition, only posts from groups that have open_archives set to true will be used (the group IDS of other groups will be silently discarded*).

*To determine which group IDs were used and which were discarded, use the group_ids field in the response. required: false default: The group IDs of every group the current user is a member of. type: string - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: latitude in: query description: > The latitude of a point around which to return posts. required: false type: number - name: longitude in: query description: > The longitude of a point around which to return posts. required: false type: number - name: radius in: query description: > The radius in meters of a circle centered at the point defined by the latitude and longitude parameters. When latitude, longitude and radius are passed, only posts within the circle defined by these parameters will be returned. required: false type: number minimum: 0 maximum: 257500 - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. required: false type: string format: date-time - name: date_max in: query description: Only posts older than this UTC date and time will be returned. required: false type: string format: date-time - name: outcomes in: query type: string required: false default: '' description: > A comma separated list of the post outcomes to return. The available post outcomes are: satisfied, withdrawn

There are also a couple special values that can be passed. If set to an empty string (the default), only posts that are not satisfied and not withdrawn and not expired are returned. If set to 'all', all posts will be returned no matter what outcome the posts have. If set to 'not-promised', only posts that are not satisfied ant not withdrawn and not expired and not promised are returned. # - name: include_reposts in: query description: > If set to 1 (the default), posts that are reposts will be included. If set to 0, reposts will be excluded. See the repost_count field of post objects for details about how reposts are identified. required: false default: 1 minimum: 0 maximum: 1 type: integer responses: 200: description: The posts and paging data. schema: type: object properties: posts: type: array items: $ref: "#/definitions/Post" num_posts: type: integer description: The total number of posts available. page: type: integer description: The page number of the posts being returned. per_page: type: integer description: The number of posts being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first post being returned (an integer between 1 and num_posts). end_index: type: integer description: The index of the last post being returned (an integer between start_index and num_posts). group_ids: type: array items: type: string description: > The IDs of the groups that the posts were retrieved from (will be null when no group IDs were used). These IDs may be a subset of the requested group IDs when a request includes group IDs for groups that are not open archives and that the current user is not a member of. If the open_archive_groups source is used, these IDs may include the IDs of open archive groups that weren't present in the group_ids parameter of the request. last_listings_view: type: string format: date-time description: > The UTC date and time when the current user last viewed the newest posts on the All Posts page (may be null).

NOTE: For this to be accurate, clients must update the last_listings_view property of the current user every time the user is shown the newest posts on the All Posts page.

NOTE: For requests using an api key instead of oauth, this field is always null. 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /users/me/posts/search: get: tags: - users summary: Search current users' posts description: > Searching posts takes the same arguments as listing posts except for the addition of the search and sort_by parameters. operationId: search_current_user_posts produces: - application/json parameters: - name: search in: query description: The search query used to find posts. required: true type: string - name: sort_by in: query description: > How to sort the posts that are returned. One of: relevance, date, active, distance

Relevance sorting will sort the posts that best match the search query first. Date sorting will sort posts from newest to oldest. Active sorting will sort active posts before satisfied, withdrawn and expired posts and then sort by date. Distance sorting will sort the closest posts first. required: false default: relevance type: string - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, taken, wanted, received, admin required: true type: string - name: sources in: query description: > A comma separated list of the post sources to retrieve posts from. The available sources are: groups, trashnothing, open_archive_groups. The trashnothing source is for public posts that are posted on trash nothing but are not associated with any group. The open_archive_groups source provides a way to easily request posts from groups that have open_archives set to true without having to pass a group_ids parameter. When passed, it will automatically return posts from open archive groups that are within the area specified by the latitude, longitude and radius parameters (or the current users' location if latitude, longitude and radius aren't passed).

NOTE: For requests using an api key instead of oauth, passing the trashnothing source or the open_archive_groups source makes the latitude, longitude and radius parameters required. required: true type: string - name: group_ids in: query description: > A comma separated list of the group IDs to retrieve posts from. This parameter is only used if the 'groups' source is passed in the sources parameter and only groups that the current user is a member of or that are open archives groups will be used (the group IDs of other groups will be silently discarded*).

NOTE: For requests using an api key instead of oauth, this field is required if the 'groups' source is passed. In addition, only posts from groups that have open_archives set to true will be used (the group IDS of other groups will be silently discarded*).

*To determine which group IDs were used and which were discarded, use the group_ids field in the response. required: false default: The group IDs of every group the current user is a member of. type: string - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: latitude in: query description: > The latitude of a point around which to return posts. required: false type: number - name: longitude in: query description: > The longitude of a point around which to return posts. required: false type: number - name: radius in: query description: > The radius in meters of a circle centered at the point defined by the latitude and longitude parameters. When latitude, longitude and radius are passed, only posts within the circle defined by these parameters will be returned. required: false type: number minimum: 0 maximum: 257500 - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. required: false type: string format: date-time - name: date_max in: query description: Only posts older than this UTC date and time will be returned. required: false type: string format: date-time - name: outcomes in: query type: string required: false default: '' description: > A comma separated list of the post outcomes to return. The available post outcomes are: satisfied, withdrawn

There are also a couple special values that can be passed. If set to an empty string (the default), only posts that are not satisfied and not withdrawn and not expired are returned. If set to 'all', all posts will be returned no matter what outcome the posts have. If set to 'not-promised', only posts that are not satisfied ant not withdrawn and not expired and not promised are returned. # - name: user_state in: query type: string required: false default: '' description: > If user_state is set, only posts matching the state specified will be returned. Only one state may be passed and it must be one of the following: viewed, replied, bookmarked

NOTE: This option will only work with oauth requests. - name: include_reposts in: query description: > If set to 1 (the default), posts that are reposts will be included. If set to 0, reposts will be excluded. See the repost_count field of post objects for details about how reposts are identified. required: false default: 1 minimum: 0 maximum: 1 type: integer responses: 200: description: The posts and paging data. schema: type: object properties: posts: type: array items: $ref: "#/definitions/PostSearchResult" num_posts: type: integer description: The total number of posts available. page: type: integer description: The page number of the posts being returned. per_page: type: integer description: The number of posts being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first post being returned (an integer between 1 and num_posts). end_index: type: integer description: The index of the last post being returned (an integer between start_index and num_posts). group_ids: type: array items: type: string description: > The IDs of the groups that the posts were retrieved from (will be null when no group IDs were used). These IDs may be a subset of the requested group IDs when a request includes group IDs for groups that are not open archives and that the current user is not a member of. If the open_archive_groups source is used, these IDs may include the IDs of open archive groups that weren't present in the group_ids parameter of the request. 400: description: Missing or invalid parameters. /users/{user_id}/posts/search: get: tags: - users summary: Search posts by a user description: > Searching posts takes the same arguments as listing posts except for the addition of the search and sort_by parameters. operationId: search_user_posts produces: - application/json parameters: - name: user_id in: path description: > The user ID of the user whose posts will be retrieved. Using 'me' as the user_id will return the posts for the current user. required: true type: string - name: search in: query description: The search query used to find posts. required: true type: string - name: sort_by in: query description: > How to sort the posts that are returned. One of: relevance, date, active, distance

Relevance sorting will sort the posts that best match the search query first. Date sorting will sort posts from newest to oldest. Active sorting will sort active posts before satisfied, withdrawn and expired posts and then sort by date. Distance sorting will sort the closest posts first. required: false default: relevance type: string - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, taken, wanted, received, admin required: true type: string - name: sources in: query description: > A comma separated list of the post sources to retrieve posts from. The available sources are: groups, trashnothing, open_archive_groups. The trashnothing source is for public posts that are posted on trash nothing but are not associated with any group. The open_archive_groups source provides a way to easily request posts from groups that have open_archives set to true without having to pass a group_ids parameter. When passed, it will automatically return posts from open archive groups that are within the area specified by the latitude, longitude and radius parameters (or all the open archive groups the requested user has posted to if latitude, longitude and radius aren't passed).

NOTE: For requests using an api key instead of oauth, passing the trashnothing source or the open_archive_groups source makes the latitude, longitude and radius parameters required. required: true type: string - name: group_ids in: query description: > A comma separated list of the group IDs to retrieve posts from. This parameter is only used if the 'groups' source is passed in the sources parameter and only groups that the current user is a member of or that are open archives groups will be used (the group IDs of other groups will be silently discarded*).

NOTE: For requests using an api key instead of oauth, this field is required if the 'groups' source is passed. In addition, only posts from groups that have open_archives set to true will be used (the group IDS of other groups will be silently discarded*).

*To determine which group IDs were used and which were discarded, use the group_ids field in the response. required: false default: The group IDs of every group the current user is a member of. type: string - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: latitude in: query description: > The latitude of a point around which to return posts. required: false type: number - name: longitude in: query description: > The longitude of a point around which to return posts. required: false type: number - name: radius in: query description: > The radius in meters of a circle centered at the point defined by the latitude and longitude parameters. When latitude, longitude and radius are passed, only posts within the circle defined by these parameters will be returned. required: false type: number minimum: 0 maximum: 257500 - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. required: false type: string format: date-time - name: date_max in: query description: Only posts older than this UTC date and time will be returned. required: false type: string format: date-time - name: outcomes in: query type: string required: false default: '' description: > A comma separated list of the post outcomes to return. The available post outcomes are: satisfied, withdrawn

There are also a couple special values that can be passed. If set to an empty string (the default), only posts that are not satisfied and not withdrawn and not expired are returned. If set to 'all', all posts will be returned no matter what outcome the posts have. If set to 'not-promised', only posts that are not satisfied ant not withdrawn and not expired and not promised are returned. # - name: include_reposts in: query description: > If set to 1 (the default), posts that are reposts will be included. If set to 0, reposts will be excluded. See the repost_count field of post objects for details about how reposts are identified. required: false default: 1 minimum: 0 maximum: 1 type: integer responses: 200: description: The posts and paging data. schema: type: object properties: posts: type: array items: $ref: "#/definitions/PostSearchResult" num_posts: type: integer description: The total number of posts available. page: type: integer description: The page number of the posts being returned. per_page: type: integer description: The number of posts being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first post being returned (an integer between 1 and num_posts). end_index: type: integer description: The index of the last post being returned (an integer between start_index and num_posts). group_ids: type: array items: type: string description: > The IDs of the groups that the posts were retrieved from (will be null when no group IDs were used). These IDs may be a subset of the requested group IDs when a request includes group IDs for groups that are not open archives and that the current user is not a member of. If the open_archive_groups source is used, these IDs may include the IDs of open archive groups that weren't present in the group_ids parameter of the request. 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /users/{user_id}/feedback: # get: # tags: # - users # summary: Retrieve feedback about a user # operationId: get_user_feedback # produces: # - application/json # parameters: # - name: user_id # in: path # description: A user ID. # required: true # type: string # responses: # 200: # description: Feedback data about the # schema: # type: object # properties: # feedback: # type: array # items: # $ref: "#/definitions/Feedback" # reviewers: # type: object # additionalProperties: # type: string # description: > # All the Users who are referenced by their user_id's in the feedback array are returned is this JSON object. # The JSON object is a map from each User's user_id to the User data. # score: # type: integer # description: The feedback score of the user (may be null). See User definition for more details. # percent_positive: # type: number # description: > # The percent of feedback that the user has received in the last year that was positive (may be null). # See User definition for more details. # # totals: # # type: object # # properties: # # all: # # type: object # # properties: # # total: # # type: integer # # description: The total count of feedback that the user has received over all time. # # positive: # # type: integer # # description: The total count of positive feedback that the user has received over all time. # # negative: # # type: integer # # description: The total count of negative feedback that the user has received over all time. # 404: # description: User not found. post: tags: - users summary: Submit feedback on a user description: > Allows the current user to submit feedback on a user. The current user can only leave feedback on a user if the feedback allowed property on that user is set to true (see User definition for more details). And the system will only store the most recent feedback submission that the current user has submitted on a user. If the current user submits feedback multiple times, the newest feedback will overwrite the older feedback. This allows users to update their feedback as long as the feedback allowed property allows it. operationId: submit_user_feedback consumes: - multipart/form-data produces: - application/json parameters: - name: user_id in: path description: A user ID. required: true type: string - name: positive in: formData description: If set to 1, the feedback is positive. If set to 0, the feedback is negative. required: true type: integer - name: content in: formData description: > A comment written by the current user about the user they are leaving feedback on. This is optional for positive feedback but is required for negative feedback. required: false type: string maxLength: 16384 - name: category in: formData description: > For positive feedback, category should not be set.

For negative feedback, category should be set to one of: NO_SHOW, UNRESPONSIVE, LATE_OR_TOO_EARLY, ITEM_NOT_AS_DESCRIBED, BROKEN_PROMISE, RUDE, RESELLER, SELLING, UNWANTED_MESSAGES, COMMUNICATION, OTHER

Below are descriptions for each of these categories:

**NO_SHOW** - The user did not show up when they said they would.
**UNRESPONSIVE** - The user failed to respond when a response was expected.
**LATE_OR_TOO_EARLY** - The user showed up later than they said they would (or too early).
**ITEM_NOT_AS_DESCRIBED** - The user gave away an item that had a misleading on incomplete description.
**BROKEN_PROMISE** - The user broke a promise.
**RUDE** - The user was rude or impolite.
**RESELLER** - The user is obtaining free items to sell on other sites without disclosing their intent to resell.
**SELLING** - The user is selling items on trash nothing.
**UNWANTED_MESSAGES** - The user is sending off-topic or unrelated messages.
**COMMUNICATION** - The users' communication is unclear, confusing or bad.
**OTHER** - This category is for anything that does not fit in any of the above categories. required: false type: string responses: 200: description: The updated user and feedback. schema: type: object properties: user: $ref: "#/definitions/User" feedback: $ref: "#/definitions/Feedback" 400: description: Missing or invalid parameters. 404: description: User not found. delete: tags: - users summary: Remove feedback on a user description: > Allows the current user to remove feedback that they left on a user. operationId: remove_user_feedback consumes: - multipart/form-data produces: - application/json parameters: - name: user_id in: path description: A user ID. required: true type: string responses: 200: description: The updated user. schema: type: object properties: user: $ref: "#/definitions/User" 400: description: Missing or invalid parameters. 404: description: User not found. /users/me/groups: get: tags: - users summary: List current users' groups operationId: get_current_user_groups consumes: - multipart/form-data produces: - application/json parameters: - name: membership in: query description: > Set the membership parameter to only return certain groups. The options are:

- **subscribed**: Only return groups the user is a member of.
- **pending-questions**: Only return groups where the user needs to respond to a new member questionnaire.
- **pending**: Only return groups where the user is waiting for their membership request to be approved (excludes groups which are pending-questions).

If unset, all groups the user is a member of and pending membership on will be returned. required: false type: string responses: 200: description: The users groups. schema: type: array items: $ref: "#/definitions/Group" 400: description: Invalid membership parameter. /users/me/notices: get: tags: - users summary: List current users' group notices operationId: get_user_group_notices consumes: - multipart/form-data produces: - application/json parameters: - name: group_ids in: query description: A comma separated list of group IDs to return notices for. If unset, notices for all the users groups will be returned. required: false type: string responses: 200: description: The users group notices. schema: type: array items: $ref: "#/definitions/GroupNotice" 400: description: Invalid group IDs. /users/{user_id}/profile-image: get: tags: - users summary: Retrieve a users' profile image description: > This is designed to be used as the src attribute of an HTML <img> tag to show the profile image of the given user. operationId: get_profile_image_file produces: - image/jpeg - image/png - image/gif parameters: - name: user_id in: path description: The user ID of the user to return the profile image of. required: true type: string - name: default in: query description: > A default image URL to use when the user has no profile image. Or to use one of the Gravatar default images, you can set default to any one of (404, mm, identicon, monsterid, wavatar, retro, blank).

To learn how the Gravatar default images options work, see the Default Image section on the page at:
https://en.gravatar.com/site/implement/images/ required: false type: string responses: 302: description: > This endpoint returns an HTTP redirect to a URL that hosts the image. So requests on this endpoint that automatically follow redirects (eg. most browsers) will be redirected to a valid image file. 400: description: Invalid default parameter. /users/me/profile-image: post: tags: - users summary: Set a profile image operationId: set_profile_image description: > Profile images must be at least 90 pixels wide and tall. And if the image used is not square it will be automatically cropped to be square. consumes: - multipart/form-data produces: - application/json parameters: - name: photo in: formData description: Photo to upload. required: false type: file - name: photo_id in: formData required: false type: string description: Photo to use (if already uploaded). - name: set_default in: formData required: false type: integer description: > Whether or not to set the photo as the users' default profile image. Set to 1 to enable and 0 to disable. default: 1 - name: crop in: formData required: false type: string description: > If the photo needs to be cropped, a JSON encoded object with the crop arguments can be passed. The supported crop arguments are below. All arguments except rotate are required.

- **original_width**: Original width of the photo before being cropped or rotated (in pixels).
- **original_height**: Original height of the photo before being cropped or rotated (in pixels).
- **x**: The x-coordinate of the top left corner of the cropped area.
- **y**: The y-coordinate of the top left corner of the cropped area.
- **size**: The size of the square cropped area.
- **rotate**: (optional) The number of degrees to rotate the image before cropping. Currently only 90, 180 and 270 are supported which correspond to rotate left, rotate upside down and rotate right.
- name: device_pixel_ratio in: formData description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The updated user and the photo. schema: type: object properties: user: $ref: "#/definitions/CurrentUser" description: The updated user. photo: $ref: "#/definitions/PhotoResult" description: The resulting photo. 400: description: Missing or invalid parameters. /users/me/profile-images: get: tags: - users summary: List current users' profile images operationId: get_profile_images produces: - application/json responses: 200: description: The users profile images. schema: type: array items: type: object properties: image: type: string description: An image URL. source: type: string description: > The source of the image. Currently one of: gravatar, facebook, google

NOTE: Additional sources may be added in the future (eg. 'trashnothing' when support for uploading custom profile images is added) so clients should take care to support arbitrary sources being returned. /users/me/post-locations: get: tags: - users summary: List current users' post locations description: Only the most recent 3 post locations are returned. operationId: get_post_locations produces: - application/json responses: 200: description: The current users' post locations. schema: type: array items: type: object properties: name: type: string description: The location name used when submitting new posts. latitude: type: number longitude: type: number put: tags: - users summary: Save a post location for the current user description: > Creates or updates a post location for the current user. Updates will happen when the name of the post location matches a previous post location. operationId: save_post_location consumes: - multipart/form-data produces: - application/json parameters: - name: name in: formData description: A name that describes the location specified by the given latitude and longitude (must be >= 2 characters and <= 30 characters). required: true type: string - name: latitude in: formData required: true type: number - name: longitude in: formData required: true type: number responses: 200: description: The current users' post locations. schema: type: array items: type: object properties: name: type: string description: The location name used when submitting new posts. latitude: type: number longitude: type: number /users/me/alerts: get: tags: - users summary: List current users' email alerts operationId: get_alerts produces: - application/json responses: 200: description: The users alerts. schema: type: array items: $ref: "#/definitions/Alert" put: tags: - users summary: Create an email alert operationId: create_alert consumes: - multipart/form-data produces: - application/json parameters: - name: search in: formData description: When a post matches this search query, an email alert will be sent. Must have a length >= 2 and < 255 characters. required: true type: string - name: types in: formData description: > A comma separated list of the post types that the alert should match against. The available post types are: offer, wanted required: true type: string responses: 200: description: The new alert. schema: $ref: "#/definitions/Alert" 400: description: Missing or invalid parameters or maximum number of alerts reached. /users/me/alerts/{alert_id}: delete: tags: - users summary: Delete an email alert operationId: delete_alert produces: - application/json parameters: - name: alert_id in: path description: The ID of the email alert to delete. required: true type: string responses: 200: description: Alert deleted. 403: description: The user doesn't have permission to access the alert. 404: description: Alert not found. # /users/me/reset-password: post: tags: - users summary: Send password reset email operationId: send_password_reset_email produces: - application/json responses: 200: description: Password reset email was sent. /users/me/resend-verification: post: tags: - users summary: Resend account verification email operationId: resend_account_verification_email produces: - application/json responses: 200: description: Verification email was resent. 400: description: Account already verified. /users/me/location: put: tags: - users summary: Update location description: > Update the current users' location. The location is used to determine which posts are shown to the user (both public posts and group posts). operationId: update_location consumes: - multipart/form-data produces: - application/json parameters: - name: name in: formData description: A name that describes the location specified by the given latitude and longitude (must be <= 128 characters). required: true type: string - name: latitude in: formData required: true type: number - name: longitude in: formData required: true type: number - name: radius in: formData description: > A radius in meters that defines a circle around the point specified by latitude and longitude. Only posts within the area specified by this circle will be shown. If set to 0, effectively disables public posts for the user. required: true type: number minimum: 0 maximum: 257500 responses: 200: description: The user with the updated location. schema: $ref: "#/definitions/CurrentUser" 400: description: Missing or invalid parameters. /users/me/email: post: tags: - users summary: Change email address description: > Change the users' current email address. A verification link will be emailed to the new email address to verify that the email account belongs to the user. The email change will not take effect until the user clicks the link in the verification email. operationId: change_email consumes: - multipart/form-data produces: - application/json parameters: - name: address in: formData description: The new email address. required: true type: string responses: 200: description: A verification email was sent to the new email address. 400: description: Invalid email address. /users/me/email/not-bouncing: put: tags: - users summary: Set users' email address as not bouncing description: > Resets an email address bouncing state to false. The users' email address may be automatically marked as bouncing again if further emails sent to it are bounced. operationId: set_email_not_bouncing produces: - application/json responses: 200: description: The updated user. schema: $ref: "#/definitions/CurrentUser" 400: description: Email not yet verified. /users/report: post: tags: - users summary: Report a user operationId: report_user consumes: - multipart/form-data produces: - application/json parameters: - name: subject in: formData description: The subject of the message. required: false type: string - name: message in: formData description: The body of the message. required: true type: string - name: user_id in: formData description: The ID of the user to report. One of user_id or user_email must be passed but only user_id will be used if both are passed. required: false type: string - name: user_email in: formData description: > The email of the user to report. Often users only know to identify other users by their email addresses so allowing users to enter an email address can be easier in certain cases. required: false type: string - name: group_id in: formData description: > The ID of the group to report the user to. This may be disregarded in cases where user_email is set and can be used to automatically identify which group the user should be reported to (because some email addresses are specific to certain groups). required: false type: string responses: 200: description: The user was reported. 400: description: Missing or invalid parameters. In particular, a user cannot report themselves. 404: description: User or group not found. /feedback: post: tags: - misc summary: Send feedback description: Allows users to send feedback about the trashnothing.com site or apps. operationId: send_feedback consumes: - multipart/form-data produces: - application/json parameters: - name: subject in: formData description: The subject. required: true type: string - name: message in: formData description: The message. required: true type: string - name: meta in: formData description: > Extra information set by the client that may be useful to contextualize the feedback (eg. operating system details, browser details, app details, device details). required: false type: string responses: 200: description: The feedback has been sent. # /stories: get: tags: - stories summary: List stories operationId: get_stories produces: - application/json parameters: - name: page in: query description: The page of stories to return. required: false default: 1 minimum: 1 type: integer - name: per_page in: query description: The number of stories to return per page (must be >= 1 and <= 50). required: false default: 20 minimum: 1 maximum: 50 type: integer - name: sort_by in: query description: > How to sort the stories that are returned. One of: date, distance, likes, views

Setting sort_by to date will sort posts from newest to oldest. Setting sort_by to distance will sort posts from nearest to farthest. Setting sort_by to likes will sort posts with the most likes first. Setting sort_by to views will show the posts with the most views first. required: false default: date type: string - name: latitude in: query description: Find groups near the given latitude and longitude. required: false type: number - name: longitude in: query description: Find groups near the given latitude and longitude. required: false type: number - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The stories and paging data. schema: type: object properties: stories: type: array items: $ref: "#/definitions/Story" # 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] post: tags: - stories summary: Submit a story operationId: submit_story consumes: - multipart/form-data produces: - application/json parameters: - name: title in: formData description: The title of the story. required: true type: string maxLength: 80 - name: content in: formData description: The content of the story. required: true type: string - name: sharing in: formData description: > Must be set to one of the following two options: public, members

When sharing is set to public, anyone will be able to view the story. When sharing is set to members, only other members will be able to view the story. required: true type: string - name: photo_ids in: formData description: A comma separated list of the IDs of the photos that should be attached to this story. required: false type: string - name: device_pixel_ratio in: formData description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The new story. schema: $ref: "#/definitions/Story" 400: description: Missing or invalid parameters. /stories/{story_id}: get: tags: - stories summary: Retrieve a story operationId: get_story produces: - application/json parameters: - name: story_id in: path description: The ID of the story to retrieve. required: true type: string - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The story. schema: $ref: "#/definitions/Story" 403: description: Story is only visible to members. 404: description: Story not found. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /stories/{story_id}/like: put: tags: - stories summary: Like a story operationId: like_story consumes: - multipart/form-data produces: - application/json parameters: - name: story_id in: path description: The ID of the story to like. required: true type: string - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The updated story. schema: $ref: "#/definitions/Story" 404: description: Story not found. /stories/{story_id}/unlike: put: tags: - stories summary: Unlike a story operationId: unlike_story consumes: - multipart/form-data produces: - application/json parameters: - name: story_id in: path description: The ID of the story to unlike. required: true type: string - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The updated story. schema: $ref: "#/definitions/Story" 404: description: Story not found. /stories/{story_id}/viewed: post: tags: - stories summary: Record story viewed description: Records every time a user views the full story (and not just a preview or snippet), operationId: viewed_story consumes: - multipart/form-data produces: - application/json parameters: - name: story_id in: path description: The ID of the story viewed. required: true type: string responses: 200: description: Story view was recorded. 404: description: Story not found. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /groups: get: tags: - groups summary: Search groups operationId: search_groups produces: - application/json parameters: - name: name in: query description: Find groups that have the given text somewhere in their name (case insensitive). required: false type: string - name: latitude in: query description: Find groups near the given latitude and longitude. required: false type: number - name: longitude in: query description: Find groups near the given latitude and longitude. required: false type: number - name: distance in: query description: > When latitude and longitude are passed, distance can optionally be passed to only return groups within a certain distance (in kilometers) from the point specified by the latitude and longitude. The distance must be > 0 and <= 150 and will default to 100. required: false default: 100 minimum: 0 maximum: 150 type: number - name: country in: query description: > Find groups in the given country where country is a 2 letter country code for the country (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ). required: false type: string - name: region in: query description: > For countries with regions (AU, CA, GB, US), search groups in a specific region as specified by the region abbreviation. The supported regions and their abbreviations are listed below.

NOTE: The region and postal_code parameters cannot be used at the same time and if both are passed then the postal_code will take priority.

---

**AU**
- QLD: Queensland
- SA: South Australia
- TAS: Tasmania
- VIC: Victoria
- WA: Western Australia
- NT: Northern Territory
- NSW: New South Wales - ACT

**CA**
- AB: Alberta
- BC: British Columbia
- MB: Manitoba
- NB: New Brunswick
- NL: Newfoundland and Labrador
- NS: Nova Scotia
- ON: Ontario
- QC: Quebec
- SK: Saskatchewan
- PE: Prince Edward Island

**GB**
- E: East
- EM: East Midlands
- LDN: London
- NE: North East
- NW: North West
- NI: Northern Ireland
- SC: Scotland
- SE: South East
- SW: South West
- WA: Wales
- WM: West Midlands
- YH: Yorkshire and the Humber

**US**
All 50 states and the District of Columbia are supported. For the abbreviations, see: https://github.com/jasonong/List-of-US-States/blob/master/states.csv required: false type: string - name: postal_code in: query description: > Find groups in the given postal code. Only a few countries support postal code searches (US, CA, AU, GB). The country parameter must be passed when the postal_code parameter is set.

NOTE: The region and postal_code parameters cannot be used at the same time and if both are passed then the postal_code will take priority. required: false type: string - name: page in: query description: The page of groups to return. required: false default: 1 minimum: 1 type: integer - name: per_page in: query description: The number of groups to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer responses: 200: description: The groups and paging data. schema: type: object properties: groups: type: array items: $ref: "#/definitions/Group" num_groups: type: integer description: The total number of groups available. page: type: integer description: The page number of the groups being returned. per_page: type: integer description: The number of groups being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first group being returned (an integer between 1 and num_groups). end_index: type: integer description: The index of the last group being returned (an integer between start_index and num_groups). 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /groups/{group_id}: get: tags: - groups summary: Retrieve a group operationId: get_group produces: - application/json parameters: - name: group_id in: path description: The ID of the group to retrieve. required: true type: string responses: 200: description: The group. schema: $ref: "#/definitions/Group" 404: description: Group not found. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /groups/multiple: get: tags: - groups summary: Retrieve multiple groups operationId: get_groups_by_ids produces: - application/json parameters: - name: group_ids in: query description: The IDs of the groups to retrieve. If more than 20 group IDs are passed, only the first 20 groups will be returned. required: true type: string responses: 200: description: The groups. schema: type: array items: $ref: "#/definitions/Group" 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /groups/subscribe: post: tags: - groups summary: Join groups description: > Request membership to one or more groups.

NOTE: Any group with a has_questions field set to true will also require answers to the groups' new member questionnaire to be submitted. Groups waiting for answers will have their membership field set to 'pending-questions'. And the questionnaire that needs to be answered can be found in the membership.questionnaire field of the group after a subscribe request is made to that group. operationId: join_groups consumes: - multipart/form-data produces: - application/json parameters: - name: group_ids in: formData description: A comma separated list of the IDs of the groups to join. required: true type: string responses: 200: description: The groups with updated membership data. schema: type: object properties: groups: type: array description: Updated data about the groups and the current users' membership to each group. items: $ref: "#/definitions/Group" over_group_limit: type: boolean description: > When this is true, it means that some of the membership requests weren't processed in order to keep the user from going over the 12 group limit (the membership field of the groups can be used to determine which requests were processed). 400: description: Missing or invalid parameters. 404: description: Group not found. /groups/{group_id}/unsubscribe: post: tags: - groups summary: Leave a group operationId: leave_group consumes: - multipart/form-data produces: - application/json parameters: - name: group_id in: path description: The ID of the group to leave. required: true type: string responses: 200: description: Updated data about the group and the current users' membership. schema: $ref: "#/definitions/Group" 400: description: The current user is not an active or pending member of the given group. 404: description: Group not found. /groups/{group_id}/contact: post: tags: - groups summary: Contact group moderators operationId: contact_moderators consumes: - multipart/form-data produces: - application/json parameters: - name: group_id in: path description: The group ID of the group whose moderators will be contacted. required: true type: string - name: subject in: formData description: The subject of the message. required: true type: string - name: message in: formData description: The body of the message. required: true type: string responses: 200: description: Message was sent to moderators. 400: description: Missing or invalid parameters. 404: description: Group not found. # /groups/{group_id}/answers: post: tags: - groups summary: Submit group answers # XXX: body parameter description only placed here b/c ReDoc doesn't display it properly with the parameter like swagger UI does description: > Submits answers to a groups' membership questionnaire.

The request body should be a JSON object mapping each question from the group membership.questionnaire.questions field to an answer (eg. {"Where do you live?": "New York City"} ). All questions are required so no null or empty string answers are allowed. operationId: submit_answers consumes: - application/json produces: - application/json parameters: - name: group_id in: path description: The group ID of the group that the user is submitting answers for. required: true type: string - name: body in: body description: > A JSON object mapping each question from the group membership.questionnaire.questions field to an answer (eg. {"Where do you live?": "New York City"} ). All questions are required so no null or empty string answers are allowed. required: true schema: type: object additionalProperties: type: string responses: 200: description: The updated group. schema: $ref: "#/definitions/Group" 400: description: Missing or invalid answers or questions were already answered or questions don't need to be answered. 404: description: Group not found. /posts: get: tags: - posts summary: List posts description: > NOTE: When paging through the posts returned by this endpoint, there will be at most 1,000 posts that can be returned (eg. 50 pages worth of posts with the default per_page value of 20). In areas where there are more than 1,000 posts, clients can use more specific query parameters to adjust which posts are returned. NOTE: Passing the latitude, longitude and radius parameters filters all posts by their location and so these parameters will temporarily override the current users' location preferences. When latitude, longitude and radius are not specified, public posts will be filtered by the current users' location preferences. operationId: get_posts produces: - application/json parameters: - name: sort_by in: query description: > How to sort the posts that are returned. One of: date, active, distance

Date sorting will sort posts from newest to oldest. Active sorting will sort active posts before satisfied, withdrawn and expired posts and then sort by date. Distance sorting will sort the closest posts first. required: false default: date type: string - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, taken, wanted, received, admin required: true type: string - name: sources in: query description: > A comma separated list of the post sources to retrieve posts from. The available sources are: groups, trashnothing, open_archive_groups. The trashnothing source is for public posts that are posted on trash nothing but are not associated with any group. The open_archive_groups source provides a way to easily request posts from groups that have open_archives set to true without having to pass a group_ids parameter. When passed, it will automatically return posts from open archive groups that are within the area specified by the latitude, longitude and radius parameters (or the current users' location if latitude, longitude and radius aren't passed).

NOTE: For requests using an api key instead of oauth, passing the trashnothing source or the open_archive_groups source makes the latitude, longitude and radius parameters required. required: true type: string - name: group_ids in: query description: > A comma separated list of the group IDs to retrieve posts from. This parameter is only used if the 'groups' source is passed in the sources parameter and only groups that the current user is a member of or that are open archives groups will be used (the group IDs of other groups will be silently discarded*).

NOTE: For requests using an api key instead of oauth, this field is required if the 'groups' source is passed. In addition, only posts from groups that have open_archives set to true will be used (the group IDS of other groups will be silently discarded*).

*To determine which group IDs were used and which were discarded, use the group_ids field in the response. required: false default: The group IDs of every group the current user is a member of. type: string - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: latitude in: query description: > The latitude of a point around which to return posts. required: false type: number - name: longitude in: query description: > The longitude of a point around which to return posts. required: false type: number - name: radius in: query description: > The radius in meters of a circle centered at the point defined by the latitude and longitude parameters. When latitude, longitude and radius are passed, only posts within the circle defined by these parameters will be returned. required: false type: number minimum: 0 maximum: 257500 - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. If unset, defaults to the current date and time minus 90 days. required: false type: string format: date-time - name: date_max in: query description: Only posts older than this UTC date and time will be returned. If unset, defaults to the current date and time. required: false type: string format: date-time - name: outcomes in: query type: string required: false default: '' description: > A comma separated list of the post outcomes to return. The available post outcomes are: satisfied, withdrawn

There are also a couple special values that can be passed. If set to an empty string (the default), only posts that are not satisfied and not withdrawn and not expired are returned. If set to 'all', all posts will be returned no matter what outcome the posts have. If set to 'not-promised', only posts that are not satisfied ant not withdrawn and not expired and not promised are returned. # - name: user_state in: query type: string required: false default: '' description: > If user_state is set, only posts matching the state specified will be returned. Only one state may be passed and it must be one of the following: viewed, replied, bookmarked

NOTE: This option will only work with oauth requests. - name: include_reposts in: query description: > If set to 1 (the default), posts that are reposts will be included. If set to 0, reposts will be excluded. See the repost_count field of post objects for details about how reposts are identified. required: false default: 1 minimum: 0 maximum: 1 type: integer responses: 200: description: The posts and paging data. schema: type: object properties: posts: type: array items: $ref: "#/definitions/Post" num_posts: type: integer description: The total number of posts available. page: type: integer description: The page number of the posts being returned. per_page: type: integer description: The number of posts being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first post being returned (an integer between 1 and num_posts). end_index: type: integer description: The index of the last post being returned (an integer between start_index and num_posts). group_ids: type: array items: type: string description: > The IDs of the groups that the posts were retrieved from (will be null when no group IDs were used). These IDs may be a subset of the requested group IDs when a request includes group IDs for groups that are not open archives and that the current user is not a member of. If the open_archive_groups source is used, these IDs may include the IDs of open archive groups that weren't present in the group_ids parameter of the request. last_listings_view: type: string format: date-time description: > The UTC date and time when the current user last viewed the newest posts on the All Posts page (may be null).

NOTE: For this to be accurate, clients must update the last_listings_view property of the current user every time the user is shown the newest posts on the All Posts page.

NOTE: For requests using an api key instead of oauth, this field is always null. 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] post: tags: - posts summary: Submit a post description: > Submits a new post. operationId: submit_post consumes: - multipart/form-data produces: - application/json parameters: - name: group_ids in: formData description: A comma separated list of group IDs to submit the post to (if any). required: false type: string - name: type in: formData description: > The type of post. One of: offer, wanted required: true type: string - name: title in: formData description: A short description of the item(s). required: true type: string minLength: 2 maxLength: 35 - name: location in: formData description: A short location description. required: true type: string minLength: 2 maxLength: 30 - name: content in: formData description: A longer description of the item(s). required: false type: string - name: fair_offer in: formData description: If set to 1, the post will be posted with the Fair Offer Policy (only valid for offer posts - see https://trashnothing.com/fair_offer_policy ). required: false type: integer default: 0 - name: latitude in: formData description: > The latitude corresponding to the location description provided.

If latitude and longitude are not provided, an attempt will be made to automatically geocode the location. If the location is unable to be geocoded, the post will be rejected* and will have to be resubmitted with a latitude and longitude corresponding to the location or resubmitted with a different location that can be automatically geocoded.

NOTE: The latitude and longitude should NOT be the users' exact location because we don't want to publicize their exact location unless their location description is their full address (which is not recommended).

*When a post is rejected because it can't be geocoded, the returned error will have its identifier property set to 'unknown-location'. required: false type: number - name: longitude in: formData description: The longitude corresponding to the location description provided. (see the NOTE in latitude description) required: false type: number - name: photo_ids in: formData description: A comma separated list of the IDs of the photos that should be attached to this post. required: false type: string - name: expires_in in: formData description: > When the post should expire. Defaults to 90 days. Any amount of time from 1 hour to 90 days can be provided. To pass a number of hours, provide the number of hours prefixed by 'h' (eg. 1hr 24hr). To pass a number of days, provide the number of days prefixed by 'd' (eg. 1d 90d).

Note that posts may not appear instantly after submission because the volunteer moderators of many groups may have additional automatic or manual review processes in place that can cause delays. So with short expirations (eg. < 8 hours), there is a chance that the post may expire before it's approved and so it will never be published. required: false type: string - name: reselling in: formData description: > For wanted posts only. If set to 1, the wanted post will show that the poster intends to resell any items that they receive in response to this post. Posters must declare if they intend to resell items. required: false type: string - name: repost in: formData description: > If the post is a repost of an existing post, this should be set to the post_id of the post that is being reposted. required: false type: string - name: session in: formData description: > A JSON string representing a temporary object that is used to store data about the submission process for a single post. The first time a post is submitted, session should be a new empty object (eg. '{}'). The session object should be persisted by the client until that post is successfully submitted and then it can be discarded so that the next post will start over with a new empty session object. Every time a post is submitted and the response indicates that the submission was not successful, the session object returned in the response should override the clients copy of the session. required: true type: string - name: preferences in: formData description: > A JSON string representing a permanent object that the client persists and modifies based on warnings returned by the post submission process and user input. Some warnings returned after submitting a post have a preference_key string property so that users can opt out of those warnings in the future. To save this opt-out preference, set the property indicated by the preference_key in the preferences object (eg. preferences[preference_key] = 1). The preferences object is never modified by the server - it is up to the client to initialize, modify and persist the preferences object. required: false type: string responses: 200: description: Post submission result. schema: type: object properties: result: type: string description: > One of: success, error, warning.

A success result indicates that the post was submitted successfully. Note that posts may not appear instantly after submission because the volunteer moderators of many groups may have additional automatic or manual review processes in place that can cause delays.

An error result indicates that there is an error with the post that should be shown to the user and the message property will contain text describing the error.

A warning result indicates that there is a warning about the post to show the user and the message property will contain a string describing the warning. A warning result doesn't prevent a post from being submitted, to continue the submission process after a warning result, just re-submit (with the updated session object) to temporarily override that specific warning. message: type: string description: > Contains text describing the reason a post was not successful. Is null on success. preference_key: type: string description: > Certain types of warnings can be opted out of. These warnings will set preference_key to a string that can be set in the preferences object by the client to opt out of that type of warning in the future (see the description of the preferences parameter for more details). Is null for errors, success and warnings that can't be opted out of. session: type: object description: > The updated session object that should override the client's copy of the session that was passed in the session parameter. Is null on success. additionalProperties: type: string identifier: type: string description: > When an error or warning is returned, this will contain a short string representing the type of error or warning that occurred. Is null on success. # XXX: would be nice to return a post for display on Your Posts page.. but there's so much processing/deduplicating that is done.. 400: description: Missing or invalid parameters. /posts/search: get: tags: - posts summary: Search posts description: > Searching posts takes the same arguments as listing posts except for the addition of the search and sort_by parameters. NOTE: When paging through the posts returned by this endpoint, there will be at most 1,000 posts that can be returned (eg. 50 pages worth of posts with the default per_page value of 20). In areas where there are more than 1,000 posts, clients can use more specific query parameters to adjust which posts are returned. operationId: search_posts produces: - application/json parameters: - name: search in: query description: The search query used to find posts. required: true type: string - name: sort_by in: query description: > How to sort the posts that are returned. One of: relevance, date, active, distance

Relevance sorting will sort the posts that best match the search query first. Date sorting will sort posts from newest to oldest. Active sorting will sort active posts before satisfied, withdrawn and expired posts and then sort by date. Distance sorting will sort the closest posts first. required: false default: relevance type: string - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, taken, wanted, received, admin required: true type: string - name: sources in: query description: > A comma separated list of the post sources to retrieve posts from. The available sources are: groups, trashnothing, open_archive_groups. The trashnothing source is for public posts that are posted on trash nothing but are not associated with any group. The open_archive_groups source provides a way to easily request posts from groups that have open_archives set to true without having to pass a group_ids parameter. When passed, it will automatically return posts from open archive groups that are within the area specified by the latitude, longitude and radius parameters (or the current users' location if latitude, longitude and radius aren't passed).

NOTE: For requests using an api key instead of oauth, passing the trashnothing source or the open_archive_groups source makes the latitude, longitude and radius parameters required. required: true type: string - name: group_ids in: query description: > A comma separated list of the group IDs to retrieve posts from. This parameter is only used if the 'groups' source is passed in the sources parameter and only groups that the current user is a member of or that are open archives groups will be used (the group IDs of other groups will be silently discarded*).

NOTE: For requests using an api key instead of oauth, this field is required if the 'groups' source is passed. In addition, only posts from groups that have open_archives set to true will be used (the group IDS of other groups will be silently discarded*).

*To determine which group IDs were used and which were discarded, use the group_ids field in the response. required: false default: The group IDs of every group the current user is a member of. type: string - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 100). required: false default: 20 minimum: 1 maximum: 100 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: latitude in: query description: > The latitude of a point around which to return posts. required: false type: number - name: longitude in: query description: > The longitude of a point around which to return posts. required: false type: number - name: radius in: query description: > The radius in meters of a circle centered at the point defined by the latitude and longitude parameters. When latitude, longitude and radius are passed, only posts within the circle defined by these parameters will be returned. required: false type: number minimum: 0 maximum: 257500 - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. If unset, defaults to the current date and time minus 90 days. required: false type: string format: date-time - name: date_max in: query description: Only posts older than this UTC date and time will be returned. If unset, defaults to the current date and time. required: false type: string format: date-time - name: outcomes in: query type: string required: false default: '' description: > A comma separated list of the post outcomes to return. The available post outcomes are: satisfied, withdrawn

There are also a couple special values that can be passed. If set to an empty string (the default), only posts that are not satisfied and not withdrawn and not expired are returned. If set to 'all', all posts will be returned no matter what outcome the posts have. If set to 'not-promised', only posts that are not satisfied ant not withdrawn and not expired and not promised are returned. # - name: user_state in: query type: string required: false default: '' description: > If user_state is set, only posts matching the state specified will be returned. Only one state may be passed and it must be one of the following: viewed, replied, bookmarked

NOTE: This option will only work with oauth requests. - name: include_reposts in: query description: > If set to 1 (the default), posts that are reposts will be included. If set to 0, reposts will be excluded. See the repost_count field of post objects for details about how reposts are identified. required: false default: 1 minimum: 0 maximum: 1 type: integer responses: 200: description: The posts and paging data. schema: type: object properties: posts: type: array items: $ref: "#/definitions/PostSearchResult" num_posts: type: integer description: The total number of posts available. page: type: integer description: The page number of the posts being returned. per_page: type: integer description: The number of posts being returned per page. num_pages: type: integer description: The total number of pages available. start_index: type: integer description: The index of the first post being returned (an integer between 1 and num_posts). end_index: type: integer description: The index of the last post being returned (an integer between start_index and num_posts). group_ids: type: array items: type: string description: > The IDs of the groups that the posts were retrieved from (will be null when no group IDs were used). These IDs may be a subset of the requested group IDs when a request includes group IDs for groups that are not open archives and that the current user is not a member of. If the open_archive_groups source is used, these IDs may include the IDs of open archive groups that weren't present in the group_ids parameter of the request. 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /posts/all: get: tags: - posts summary: List all posts description: > This endpoint provides an easy way to get a feed of all the publicly published posts on trash nothing. It provides access to all publicly published offer and wanted posts from the last 30 days. The posts are sorted by date (newest first).

There are fewer options for filtering, sorting and searching posts with this endpoint but there is no 1,000 post limit and posts that are crossposted to multiple groups are not merged together in the response. In most cases, crossposted posts are easy to detect because they have the same user_id, title and content. operationId: get_all_posts produces: - application/json parameters: - name: types in: query description: > A comma separated list of the post types to return. The available post types are: offer, wanted required: true type: string - name: date_min in: query description: > Only posts newer than or equal to this UTC date and time will be returned. The UTC date and time used must be within a day or less of date_max. And the date and time must be within the last 30 days. And the date and time must be rounded to the nearest second. required: true type: string format: date-time - name: date_max in: query description: > Only posts older than this UTC date and time will be returned. The UTC date and time used must be within a day or less of date_min. And the date and time must be rounded to the nearest second. required: true type: string format: date-time - name: per_page in: query description: The number of posts to return per page (must be >= 1 and <= 50). required: false default: 20 minimum: 1 maximum: 50 type: integer - name: page in: query description: The page of posts to return. required: false default: 1 minimum: 1 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The posts. schema: type: object properties: posts: type: array items: $ref: "#/definitions/Post" 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /posts/all/changes: get: tags: - posts summary: List all post changes description: > This endpoint provides an easy way to get a feed of all the changes that have been made to publicly published posts on trash nothing. Similar to the /posts/all endpoint, only data from the last 30 days is available and the changes are sorted by date (newest first). Every change includes the date of the change, the post_id of the post that was changed and the type of change.

The different types of changes that are returned are listed below.

- deleted
- undeleted
- satisfied
- promised
- unpromised
- withdrawn
- edited

For edited changes, clients can use the retrieve post API endpoint to get the edits that have been made to the post. operationId: get_all_posts_changes produces: - application/json parameters: - name: date_min in: query description: > Only changes newer than or equal to this UTC date and time will be returned. The UTC date and time used must be within a day or less of date_max. And the date and time must be within the last 30 days. And the date and time must be rounded to the nearest second. required: true type: string format: date-time - name: date_max in: query description: > Only changes older than this UTC date and time will be returned. The UTC date and time used must be within a day or less of date_min. And the date and time must be rounded to the nearest second. required: true type: string format: date-time - name: per_page in: query description: The number of changes to return per page (must be >= 1 and <= 50). required: false default: 20 minimum: 1 maximum: 50 type: integer - name: page in: query description: The page of changes to return. required: false default: 1 minimum: 1 type: integer responses: 200: description: The changes. schema: type: object properties: changes: type: array items: type: object properties: post_id: type: string date: type: string format: date-time description: The UTC date and time when the post was changed. type: type: string description: > The type of change. One of: deleted, undeleted, satisfied, promised, unpromised, withdrawn, edited, expired 400: description: Missing or invalid parameters. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /posts/{post_id}/display: get: tags: - posts summary: Retrieve post display data description: > Retrieve a post and other data related to the post that is useful for displaying the post such as data about the user who posted the post and the groups the post was posted on. operationId: get_post_and_related_data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to retrieve. required: true type: string responses: 200: description: The post and related data. schema: type: object properties: post: $ref: "#/definitions/Post" author: $ref: "#/definitions/User" author_posts: type: array description: > Other active posts from the post author in the last 90 days. A maximum of 30 posts will be returned. items: $ref: "#/definitions/Post" author_offer_count: type: integer description: Count of offer posts made by the post author in the last 90 days. author_wanted_count: type: integer description: Count of wanted posts made by the post author in the last 90 days. groups: type: array description: The groups the post is published on. items: $ref: "#/definitions/Group" user_can_reply: type: boolean description: > Whether or not the current user (if any) can reply to this post. Unverified users cannot reply to posts until they verify their account. feedback: type: array description: Feedback the current user has left on the post author. items: $ref: "#/definitions/Feedback" viewed: type: boolean description: Whether or not the current user has previously viewed this post. Will be null for api key requests and for the current users' posts. replied: type: boolean description: Whether or not the current user has replied to this post. Will be null for api key requests and for the current users' posts. bookmarked: type: boolean description: Whether or not the current user has bookmarked this post. Will be null for api key requests and for the current users' posts. 403: description: The user doesn't have permission to access the post. 404: description: Post not found. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /posts/{post_id}: get: tags: - posts summary: Retrieve a post operationId: get_post produces: - application/json parameters: - name: post_id in: path description: The ID of the post to retrieve. required: true type: string responses: 200: description: The post. schema: $ref: "#/definitions/Post" 403: description: The user doesn't have permission to access the post. 404: description: Post not found. security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] put: tags: - posts summary: Update a post description: > Users can update posts to fix mistakes with their post, add photos, or add more details about the items. Updates should not be used to say that items in a post have been taken or received since the post satisfy endpoint is designed to do that. operationId: update_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to update. required: true type: string - name: type in: formData description: > The type of post. One of: offer, wanted required: true type: string - name: title in: formData description: A short description of the item(s). required: true type: string minLength: 2 maxLength: 35 - name: location in: formData description: A short location description. required: true type: string minLength: 2 maxLength: 30 - name: content in: formData description: A longer description of the item(s). required: false type: string - name: fair_offer in: formData description: If set to 1, the post will be posted with the Fair Offer Policy (only valid for offer posts - see https://trashnothing.com/fair_offer_policy ). required: false type: integer default: 0 - name: latitude in: formData description: > The latitude corresponding to the location description provided.

If latitude and longitude are not provided, an attempt will be made to automatically geocode the location. If the location is unable to be geocoded, the post will be rejected* and will have to be resubmitted with a latitude and longitude corresponding to the location or resubmitted with a different location that can be automatically geocoded.

NOTE: The latitude and longitude should NOT be the users' exact location because we don't want to publicize their exact location unless their location description is their full address (which is not recommended).

*When a post is rejected because it can't be geocoded, the returned error will have its identifier property set to 'unknown-location'. required: false type: number - name: longitude in: formData description: The longitude corresponding to the location description provided. (see the NOTE in latitude description) required: false type: number - name: photo_ids in: formData description: A comma separated list of the IDs of the photos that should be attached to this post. required: false type: string - name: expires_in in: formData description: > When the post should expire. Any amount of time from 1 hour to 90 days can be provided. To pass a number of hours, provide the number of hours prefixed by 'h' (eg. 1hr 24hr). To pass a number of days, provide the number of days prefixed by 'd' (eg. 1d 90d).

Note that updates may not appear instantly after submission because the volunteer moderators of many groups may have additional automatic or manual review processes in place that can cause delays. So with short expirations (eg. < 8 hours), there is a chance that the post may expire before the update is approved and so it will never be published.

NOTE: The max expiration for a post is 90 days after the post is published. So updates to posts that try to set an longer expiration will be silently changed to just apply the max expiration. required: false type: string - name: reselling in: formData description: > For wanted posts only. If set to 1, the wanted post will show that the poster intends to resell any items that they receive in response to this post. Posters must declare if they intend to resell items. required: false type: string - name: session in: formData description: > A JSON string representing a temporary object that is used to store data about the update process for a single post. The first time a post update is submitted, session should be a new empty object (eg. '{}'). The session object should be persisted by the client until that update is successfully submitted and then it can be discarded so that the next update will start over with a new empty session object. Every time an update is submitted and the response indicates that the submission was not successful, the session object returned in the response should override the clients copy of the session. required: true type: string - name: preferences in: formData description: > A JSON string representing a permanent object that the client persists and modifies based on warnings returned by the update submission process and user input. Some warnings returned after submitting an update have a preference_key string property so that users can opt out of those warnings in the future. To save this opt-out preference, set the property indicated by the preference_key in the preferences object (eg. preferences[preference_key] = 1). The preferences object is never modified by the server - it is up to the client to initialize, modify and persist the preferences object. required: false type: string responses: 200: description: Post update result. schema: type: object properties: result: type: string description: > One of: success, error, warning.

A success result indicates that the post update was submitted successfully. Note that post updates may not appear instantly after submission because the volunteer moderators of many groups may have additional automatic or manual review processes in place that can cause delays.

An error result indicates that there is an error with the post that should be shown to the user and the message property will contain text describing the error.

A warning result indicates that there is a warning about the post update to show the user and the message property will contain a string describing the warning. A warning result doesn't prevent a post update from being submitted, to continue the submission process after a warning result, just re-submit (with the updated session object) to temporarily override that specific warning. message: type: string description: > Contains text describing the reason a post update was not successful. Is null on success. preference_key: type: string description: > Certain types of warnings can be opted out of. These warnings will set preference_key to a string that can be set in the preferences object by the client to opt out of that type of warning in the future (see the description of the preferences parameter for more details). Is null for errors, success and warnings that can't be opted out of. session: type: object description: > The updated session object that should override the client's copy of the session that was passed in the session parameter. Is null on success. additionalProperties: type: string identifier: type: string description: > When an error or warning is returned, this will contain a short string representing the type of error or warning that occurred. Is null on success. 400: description: Missing or invalid parameters. 403: description: The user doesn't have permission to edit the post. 404: description: Post not found. delete: tags: - posts summary: Delete a post description: > Users can delete posts they have made that have been satisfied or withdrawn or that have expired. Deleting posts isn't intended to be a normal part of the posting process since it makes reposting and viewing old posts harder. operationId: delete_post produces: - application/json parameters: - name: post_id in: path required: true type: string responses: 200: description: Post deleted. 400: description: Post cannot be deleted until it is satisfied, withdrawn or expired. 403: description: The user doesn't have permission to delete the post. 404: description: Post not found. /posts/multiple: get: tags: - posts summary: Retrieve multiple posts operationId: get_posts_by_ids produces: - application/json parameters: - name: post_ids in: query description: > A comma separated list of the post IDs. If more than 10 post IDs are passed, only the first 10 posts will be returned. required: true type: string responses: 200: description: The posts. schema: type: object properties: posts: type: array items: $ref: "#/definitions/Post" not_found: description: The IDs of posts that weren't found (may have been deleted or never existed). type: array items: type: string forbidden: description: The IDs of posts that are forbidden for the current user. type: array items: type: string security: - oauth2_implicit: - basic - oauth2_code: - basic - api_key: [] /posts/{post_id}/reply: post: tags: - posts summary: Reply to a post description: Send a reply to a post from the current user to the post author. operationId: reply_to_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to reply to. required: true type: string - name: message in: formData description: The message to send to the post author. required: true type: string - name: photo_ids in: formData description: A comma separated list of the IDs of the photos that should be attached to this reply. required: false type: string responses: 200: description: The reply has been sent. 400: description: Missing message parameter or post has been satisfied or withdrawn or expired or the post author is blocked. 403: description: The user doesn't have permission to reply to the post. 404: description: Post not found. /posts/{post_id}/report: post: tags: - posts summary: Report a post description: Reports a post to be reviewed by the moderators. operationId: report_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path required: true type: string - name: reason in: formData description: > The reason that this post is being reported. Must be one of: 'spam', 'not free (for sale/trade/borrow)', 'illegal item', 'not family-friendly', 'other', 'mislabeled: is a Want', 'mislabeled: is an Offer'.

NOTE: If reason is set to 'other', the details parameter is required to be set. required: true type: string - name: details in: formData description: > An explanation from the current user for why they are reporting this post. This is useful for users to provide evidence or explain why there is a problem with the post.

NOTE: If reason is set to 'other', details are required. required: false type: string responses: 200: description: The post has been reported. 400: description: Invalid reason parameter or missing details. 404: description: Post not found. # /posts/{post_id}/bookmark: put: tags: - posts summary: Bookmark a post operationId: bookmark_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path required: true type: string responses: 200: description: The post has been bookmarked. 403: description: The user doesn't have permission to view the post. 404: description: Post not found. delete: tags: - posts summary: Delete a post bookmark operationId: delete_bookmark produces: - application/json parameters: - name: post_id in: path required: true type: string responses: 200: description: Bookmark deleted. 404: description: Post not found. /posts/{post_id}/satisfy: put: tags: - posts summary: Satisfy a post description: Mark an offer or wanted post by the current user as satisfied (eg. an offer has been taken or a wanted has been received). operationId: satisfy_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to satisfy. required: true type: string responses: 200: description: The updated post. schema: $ref: "#/definitions/Post" 400: description: Invalid summary or the post is not an offer or wanted post or the post has been withdrawn or has expired. 403: description: The user doesn't have permission to access the post. 404: description: Post not found. /posts/{post_id}/withdraw: put: tags: - posts summary: Withdraw a post description: Mark an offer or wanted post by the current user as withdrawn. operationId: withdraw_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to withdraw. required: true type: string responses: 200: description: The updated post. schema: $ref: "#/definitions/Post" 400: description: The post is not an offer or wanted post or the post has already been satisfied or expired. 403: description: The user doesn't have permission to access the post. 404: description: Post not found. /posts/{post_id}/promise: put: tags: - posts summary: Promise an offer post description: > Mark an offer by the current user as promised to someone. This helps people viewing the post know that the items being offered may soon be given away as long as the person who was promised the items picks them up. operationId: promise_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to promise. required: true type: string responses: 200: description: The updated post. schema: $ref: "#/definitions/Post" 400: description: The post is not an offer post or the post has already been satisfied or withdrawn or expired. 403: description: The user doesn't have permission to access the post. 404: description: Post not found. /posts/{post_id}/unpromise: put: tags: - posts summary: Unpromise an offer post description: Mark an offer by the current user as unpromised. operationId: unpromise_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to unpromise. required: true type: string responses: 200: description: The updated post. schema: $ref: "#/definitions/Post" 400: description: The post is not an offer post or the post has already been satisfied or withdrawn. 403: description: The user doesn't have permission to access the post. 404: description: Post not found. /posts/{post_id}/share: post: tags: - posts summary: Share a post description: Forwards a copy of the post to the current user so that they can forward it to friends. operationId: share_post consumes: - multipart/form-data produces: - application/json parameters: - name: post_id in: path description: The ID of the post to share. required: true type: string responses: 200: description: Post shared. 403: description: The user doesn't have permission to access the post. 404: description: Post not found. /photos: post: tags: - photos summary: Create a photo operationId: upload_photo consumes: - multipart/form-data produces: - application/json parameters: - name: photo in: formData description: Photo to upload. required: true type: file - name: device_pixel_ratio in: formData description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: Photo created. schema: $ref: "#/definitions/PhotoResult" 400: description: Invalid photo. /photos/{photo_id}/rotate: post: tags: - photos summary: Rotate a photo operationId: rotate_photo produces: - application/json parameters: - name: photo_id in: path required: true type: string - name: degrees in: query required: true type: integer description: Rotation in degrees - currently only 90, 180 and 270 are supported which correspond to rotate left, rotate upside down and rotate right. - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: Photo rotated. schema: $ref: "#/definitions/PhotoResult" 400: description: Invalid photo. 403: description: The user doesn't have permission to rotate the photo. 404: description: Photo not found. /photos/{photo_id}: delete: tags: - photos summary: Delete a photo operationId: delete_photo produces: - application/json parameters: - name: photo_id in: path required: true type: string responses: 200: description: Photo deleted. 400: description: Invalid photo. 403: description: The user doesn't have permission to delete the photo. 404: description: Photo not found. /photos/multiple: get: tags: - photos summary: Retrieve multiple photos operationId: get_photos_by_ids produces: - application/json parameters: - name: photo_ids in: query description: The IDs of the photos to retrieve. If more than 50 photo IDs are passed, only the first 50 photos will be returned. required: true type: string - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The photos. schema: type: array items: $ref: "#/definitions/PhotoResult" 400: description: Missing or invalid parameters. /conversations: get: tags: - messages summary: List conversations operationId: get_conversations consumes: - multipart/form-data produces: - application/json parameters: - name: category in: query description: > Used to filter messases by category. Must be set to one of the following three categories: inbox, archived, blocked required: false type: string default: inbox - name: page in: query description: The page of conversations to return. required: false default: 1 minimum: 1 type: integer - name: per_page in: query description: The number of conversations to return per page (must be >= 1 and <= 30). required: false default: 10 minimum: 1 maximum: 30 type: integer - name: num_messages in: query description: > The number of recent messages to return with each conversation. Additional messages can be retrieved using get conversation messages endpoint. required: false type: integer default: 10 minimum: 0 maximum: 30 - name: include_num_unread in: query description: > If set to 1, the num_unread field in the response will be set to the count of the total number of conversations that have unread messages.

This is useful for showing users the total number of unread messages that they have in their inbox. Calculating the count will slow the request down a bit so setting this should be avoided for requests where it's not needed (eg. requesting archived or blocked conversations or requests that are just paging through older conversations). required: false default: 0 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The conversations and paging data. schema: type: object properties: conversations: type: array items: $ref: "#/definitions/Conversation" page: type: integer per_page: type: integer num_unread: type: integer description: > If the include_num_unread parameter is set to 1, this will be set to the total number of conversations that have unread messages matching the query parameters of the request. If the include_num_unread parameter is set to 0, this will be null. 400: description: Invalid parameters. /conversations/search: get: tags: - messages summary: Search conversations operationId: search_conversations description: Searches all conversations except blocked conversations. consumes: - multipart/form-data produces: - application/json parameters: - name: search in: query description: The search query used to find conversations and messages. required: true type: string - name: page in: query description: The page of conversations to return. required: false default: 1 minimum: 1 type: integer - name: per_page in: query description: The number of conversations to return per page (must be >= 1 and <= 30). required: false default: 10 minimum: 1 maximum: 30 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The conversations and paging data. schema: type: object properties: conversations: type: array items: $ref: "#/definitions/Conversation" page: type: integer per_page: type: integer search: type: string 400: description: Invalid parameters. /conversations/mark-all-read: put: tags: - messages summary: Mark all conversations as read operationId: mark_all_conversations_read consumes: - multipart/form-data produces: - application/json parameters: - name: message_id in: formData description: The message_id of the most recent message from the conversations that the client has downloaded. required: true type: string responses: 200: description: Conversations marked as read. 400: description: Invalid message_id. /conversations/archive-all: put: tags: - messages summary: Archive all conversations operationId: archive_all_conversations consumes: - multipart/form-data produces: - application/json parameters: - name: message_id in: formData description: The message_id of the most recent message from the conversations that the client has downloaded. required: true type: string responses: 200: description: Conversations archived. 400: description: Invalid message_id. /conversations/{conversation_id}/block: put: tags: - messages summary: Block conversation operationId: block_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to block. required: true type: string responses: 200: description: Conversation blocked. 400: description: Conversations with moderators cannot be blocked. 403: description: The user doesn't have permission to modify this conversation. 404: description: Conversation not found. /conversations/{conversation_id}/unblock: put: tags: - messages summary: Unblock conversation operationId: unblock_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to unblock. required: true type: string responses: 200: description: Conversation unblocked. 403: description: The user doesn't have permission to modify this conversation. 404: description: Conversation not found. /conversations/{conversation_id}/archive: put: tags: - messages summary: Archive conversation operationId: archive_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to archive. required: true type: string responses: 200: description: Conversation archived. 403: description: The user doesn't have permission to modify this conversation. 404: description: Conversation not found. /conversations/{conversation_id}/unarchive: put: tags: - messages summary: Unarchive conversation operationId: unarchive_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to unarchive. required: true type: string responses: 200: description: Conversation unarchived. 403: description: The user doesn't have permission to modify this conversation. 404: description: Conversation not found. # /conversations/{conversation_id}/mark-read: put: tags: - messages summary: Mark conversation as read operationId: mark_conversation_read consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to mark as read. required: true type: string - name: message_id in: formData description: The ID of the newest message in the conversation that the current user has read. required: true type: string responses: 200: description: Conversation marked as read. 400: description: Invalid parameters. 403: description: The user doesn't have permission to modify this conversation. 404: description: Conversation or message not found. /conversations/{conversation_id}/reply: post: tags: - messages summary: Reply to conversation operationId: reply_to_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to reply to. required: true type: string - name: content in: formData description: The content of the reply. required: true type: string - name: photo_ids in: formData description: A comma separated list of the IDs of the photos that should be attached to this message. required: false type: string - name: device_pixel_ratio in: formData description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number responses: 200: description: The new message sent to the conversation. schema: $ref: "#/definitions/Message" 400: description: Invalid parameters or duplicate reply or conversation is blocked. 403: description: The user doesn't have permission to reply to the conversation. 404: description: Conversation not found. /conversations/{conversation_id}/messages: get: tags: - messages summary: List conversation messages operationId: get_conversation_messages consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to return messages from. required: true type: string - name: page in: query description: The page of messages to return. required: false default: 1 minimum: 1 type: integer - name: per_page in: query description: The number of messages to return per page (must be >= 1 and <= 30). required: false default: 10 minimum: 1 maximum: 30 type: integer - name: device_pixel_ratio in: query description: Client device pixel ratio used to determine thumbnail size (default 1.0). required: false default: 1.0 type: number - name: include_conversation in: query description: If set to 1, the conversation will be returned along with the messages. required: false type: integer default: 0 responses: 200: description: > The messages and page data. The conversation data is optional and is only returned if the include_conversation parameter is set. schema: type: object properties: messages: type: array items: $ref: "#/definitions/Message" page: type: integer per_page: type: integer conversation: $ref: "#/definitions/Conversation" 400: description: Invalid parameters. 403: description: The user doesn't have permission to access the conversation. 404: description: Conversation not found. /conversations/{conversation_id}/report: post: tags: - messages summary: Report conversation operationId: report_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to report. required: true type: string - name: reason in: formData description: A user provided reason why the conversation is being reported. required: true type: string responses: 200: description: Conversation reported. 400: description: Empty reason parameter. 403: description: The user doesn't have permission to report the conversation. 404: description: Conversation not found. /conversations/{conversation_id}: delete: tags: - messages summary: Delete conversation operationId: delete_conversation consumes: - multipart/form-data produces: - application/json parameters: - name: conversation_id in: path description: The ID of the conversation to delete. required: true type: string - name: message_id in: query description: The ID of the newest message in the conversation that the client has downloaded. required: true type: string # responses: 200: description: Conversation deleted. 400: description: Invalid parameters. 403: description: The user doesn't have permission to modify this conversation. 404: description: Conversation or message not found. securityDefinitions: oauth2_implicit: type: oauth2 authorizationUrl: https://trashnothing.com/oauth2/authorize flow: implicit scopes: basic: Provides full access to a user's account description: > This is the default OAuth2 flow for new apps. oauth2_code: type: oauth2 authorizationUrl: https://trashnothing.com/oauth2/authorize tokenUrl: https://trashnothing.com/oauth2/token flow: accessCode scopes: basic: Provides full access to a user's account description: > This OAuth2 flow is designed for server side apps and is not enabled by default for new apps. If you would like to use this flow for your app, contact us through the [trash nothing Developer page](https://trashnothing.com/developer). api_key: type: apiKey name: api_key in: query description: > Provides access to specific public API endpoints which don't require user authorization.

The API currently allows api key access to list, search and retrieve posts (for public posts and posts on open archive groups) and to list, search and retrieve groups.

NOTE: Some API endpoints behave differently when requests are made using api keys instead of oauth (because api key requests have no user associated with them). Check the documentation for each endpoint for a description of the differences. definitions: GeolocateBounds: description: > Two bounding boxes that make using Google Maps' geocoder easier.

The default bounding box defines the area in which the post is probably located. This is useful for providing a bounds to Google Maps geocoder.

The limit bounding box is a larger bounding box that contains the default bounding box. This is useful for discarding Google Maps geocoding results that are outside of this bounding box. type: object properties: default: $ref: "#/definitions/BoundingBox" limit: $ref: "#/definitions/BoundingBox" BoundingBox: description: A geographic bounding box defined by its southwest and northeast points. type: object properties: southwest: type: object description: The point defining the southwest corner of the bounding box. properties: latitude: type: number longitude: type: number northeast: type: object description: The point defining the northeast corner of the bounding box. properties: latitude: type: number longitude: type: number example: southwest: latitude: 51.0025285305 longitude: -3.5323240284 northeast: latitude: 52.8293255665 longitude: -0.600956182 PhotoResult: description: The result of uploading or editing a photo. type: object properties: photo_id: type: string thumbnail: type: object description: Photo thumbnail data. properties: url: type: string width: type: integer height: type: integer example: photo_id: 987-423 thumbnail: url: https://trashnothing.com/img/2018-02-02/307731-20180119_155358.90x120.jpg width: 90 height: 120 PostSearchResult: allOf: - $ref: "#/definitions/Post" - type: object properties: search_title: type: string description: > The post subject as HTML with the parts of the subject that matched the search query (if any) wrapped in HTML span tags with the class 'highlight'. (eg. <span class="highlight">matched words</span>). May be null if none of the words in the subject matched the search query. search_content: type: string description: > A snippet of the post content as HTML with the parts of the content that matched the search query (if any) wrapped in an HTML span tags with the class 'highlight' (eg. <span class="highlight">matched words</span>). May be null if none of the words in the post content matched the search query.

NOTE: This is not the full content of the post It is just a snippet of around 200 characters that can be used to display the parts of the post content relevant to the search query. example: post_id: 25997431 group_id: 81 user_id: 82928 title: Microwave Oven (Greenfield) content: > Panasonic microwave oven in good working order 800 W power and turntable inside Has all the normal microwave functions plus grill elements for browning Comes with original instructions booklet It's an old microwave and could do with a bit of a clean, but still works very well date: "2018-02-18T17:11:38" type: offer outcome: null latitude: 42.961404 longitude: -88.012586 footer: null photos: null expiration: "2018-04-18T17:11:38" reselling: false url: https://trashnothing.com/post/25997431/microwave-oven-greenfield repost_count: 0 search_title: Microwave Oven (Greenfield) search_content: Panasonic microwave oven in good working order 800 W power and turntable Photo: type: object properties: photo_id: type: string thumbnail: type: string description: A URL to a thumbnail of this photo. The size of the thumbnail depends on the device_pixel_ratio parameter and it is not guaranteed to be square. url: type: string description: A URL to a large version of this photo (but not necessarily the largest size available). blurhash: type: string description: > A blurhash of the photo that can be used as a placeholder while the photo is loading (see: https://github.com/woltapp/blurhash). May be null if no blurhash is available and the length of the blurhash can vary based on the photo. images: type: array description: All the versions of this photo ordered from smallest to largest. This list is guaranteed to include the photos specified by the above thumbnail and url properties. items: type: object properties: url: type: string width: type: integer height: type: integer example: photo_id: 695624-768616 thumbnail: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg blurhash: 'TkJ7jsoz%f~VoLxu-pWCWB-oj[M|' images: - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg width: 90 height: 120 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.180x240.jpg width: 180 height: 240 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.270x360.jpg width: 270 height: 360 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg width: 375 height: 500 Post: description: An offer, wanted, admin, taken or received post. type: object properties: post_id: type: string source: type: string description: > The source of the post. One of: groups, trashnothing, open_archive_groups. A value of groups or open_archive_groups indicates the post is from a group and the group_id field will contain the ID of the group. A value of trashnothing indicates the post is a public post not associated with any group. group_id: type: string description: > The group ID of the post. For public posts, this is always null. user_id: type: string title: type: string content: type: string date: type: string format: date-time description: The UTC date and time when the post was published. type: type: string description: > The type of post. One of: offer, taken, wanted, received, admin outcome: type: string description: > For offer and wanted posts, this indicates the outcome of the post which is null if no outcome has been set yet.

Offer post outcomes will be one of: satisfied, withdrawn, promised, expired

Wanted post outcomes will be one of: satisfied, withdrawn, expired

For all other posts, outcome is always null. latitude: type: number description: May be null if a post hasn't been mapped. longitude: type: number description: May be null if a post hasn't been mapped. footer: type: string description: Some groups add footers to posts that are separate and sometimes unrelated to the post itself - such as reminders about group rules or features (may be null). photos: type: array description: Details about the photos associated with this post (may be null if there are no photos). items: $ref: "#/definitions/Photo" expiration: type: string format: date-time description: > The UTC date and time when the post will expire. Currently only offer and wanted posts expire. For all other posts, expiration is always null. reselling: type: boolean description: > For wanted posts, whether the item is being requested in order to resell it or not. Will be null for all posts that are not wanted posts and for wanted posts where the poster hasn't indicated whether or not they intend to resell the item they are requesting. url: type: string description: The link to use to view the post on the trash nothing site. repost_count: type: integer description: > The count of how many times this post has been reposted in the last 90 days. A value of zero is used to indicate that the post is not a repost. The count is specific to the source of the post (eg. the specific group the post is on). If a post is crossposted to multiple groups, the repost_count of the post on each group may be different for each group depending on how many times the post has been posted on that group in the last 90 days. example: post_id: 3171898 group_id: 6 user_id: 2933 title: Ultrasonic diffuser (Downtown Toronto) content: This ultrasonic diffuser creates an aroma in your home. It comes with two essential oils - mint and lavender. date: "2018-02-05T15:10:21" type: offer outcome: satisfied latitude: 43.653226 longitude: -79.383184 footer: null photos: - photo_id: 695624-768616 thumbnail: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg images: - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg width: 90 height: 120 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.180x240.jpg width: 180 height: 240 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.270x360.jpg width: 270 height: 360 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg width: 375 height: 500 expiration: "2018-03-05T15:10:21" reselling: false url: https://trashnothing.com/post/3171898/ultrasonic-diffuser-downtown-torronto repost_count: 1 Conversation: description: A conversation between the current user and another user. type: object properties: conversation_id: type: string user: description: > The user that the conversation is with (this is not the current user). This may be set to null if the user this conversation was with removed their account. $ref: "#/definitions/User" last_message_date: type: string format: date-time description: The UTC date and time of the last message in this conversation. num_unread_messages: type: integer description: The count of how many unread messages this conversation has. blocked: type: boolean description: Whether or not this conversation is blocked. archived: type: boolean description: Whether or not this conversation is archived. messages: type: array description: The latest messages in this conversation. items: $ref: "#/definitions/Message" example: conversation_id: 38914 user: user_id: 2946512 username: fred gibson country: GB profile_image: https://lh3.googleusercontent.com/-1qVLzuOCyYg/AAAAAAAAAAI/AAAAAAAAAAA/0aGNzRAO61c/s64-c/100783935580725962164.jpg member_since: "2017-01-27T06:35:55" firstname: null lastname: null about_me: Just an old fisherman looking to reuse more. last_message_date: "2019-07-24T22:51:09" num_unread_messages: 1 blocked: false archived: false messages: - message_id: 10199633 from_user_id: 2946512 to_user_id: 119458 date: "2019-07-24T22:29:10" subject: Dining Table and 4 Chairs content: Here are some photos and the directions for pick up. email_attachments: - Directions and map.pdf photos: - photo_id: 695624-768616 thumbnail: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg images: - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg width: 90 height: 120 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.180x240.jpg width: 180 height: 240 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.270x360.jpg width: 270 height: 360 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg width: 375 height: 500 Message: description: A message between two users. type: object properties: message_id: type: string from_user_id: type: string description: The ID of the user that sent the message (the sender). to_user_id: type: string description: The ID of the user that received the message (the recipient). date: type: string format: date-time description: The UTC date and time when the message was sent. subject: type: string description: > Because many messages are received by email, all messages have a subject. The subject is often useful to allow the recipient to determine which post a message may be referring to. In rare cases, some senders send emails with a subject and but no email body which causes the message content to be an empty string. content: type: string description: The content of the message. # email_attachments: type: array description: > Every message a user receives is made available via the API and is sent to the user by email. Some messages may contain unsupported attachments that are not available by the API but are emailed to the user (eg. documents, videos, zip files). The email_attachments field provides the names of all the unsupported attachments that were emailed to the user (will be null if there are no unsupported attachments). items: type: string photos: type: array description: Details about the photos associated with this message (may be null if there are no photos). items: $ref: "#/definitions/Photo" post: $ref: "#/definitions/Post" description: The post referenced by this message. May be null if the message couldn't be matched to any post. example: message_id: 10199633 from_user_id: 2946512 to_user_id: 119458 date: "2019-07-24T22:29:10" subject: Dining Table and 4 Chairs content: Here are some photos and the directions for pick up. email_attachments: - Directions and map.pdf photos: - photo_id: 695624-768616 thumbnail: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg images: - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg width: 90 height: 120 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.180x240.jpg width: 180 height: 240 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.270x360.jpg width: 270 height: 360 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg width: 375 height: 500 post: null Story: description: A user story type: object properties: story_id: type: string title: type: string content: type: string date: type: string format: date-time description: The UTC date and time when the post was published. user: description: The user that submitted the story. $ref: "#/definitions/User" like_count: type: integer description: The number of people who have liked this story. user_liked: type: boolean description: Whether or not the current user has liked this story or not. share_url: type: string description: A URL that can be used to share the story (may be null if the story is not public). photos: type: array description: Details about the photos associated with this story (may be null if there are no photos). items: $ref: "#/definitions/Photo" example: story_id: 7584 title: Sharing is caring content: People helping people - it doesn't get better than this! date: "2020-04-25T10:26:32" user: user_id: 2946512 username: fred gibson country: GB profile_image: https://lh3.googleusercontent.com/-1qVLzuOCyYg/AAAAAAAAAAI/AAAAAAAAAAA/0aGNzRAO61c/s64-c/100783935580725962164.jpg member_since: "2017-01-27T06:35:55" firstname: null lastname: null about_me: Just an old fisherman looking to reuse more. like_count: 3 share_url: https://trashnothing.com/story/7584 photos: - photo_id: 695624-768616 thumbnail: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg images: - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.90x120.jpg width: 90 height: 120 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.180x240.jpg width: 180 height: 240 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.270x360.jpg width: 270 height: 360 - url: https://trashnothing.com/img/2018-02-05/cfsbfm-39051735845_379baab73f.375x500.jpg width: 375 height: 500 Alert: description: A search alert that the user has created so that they can be notified when new posts match the search query specified by the alert. type: object properties: alert_id: type: string user_id: type: string search: type: string description: The search phrase that the alert triggers on. types: type: array description: > A list of the post types that the alert is set to match against. The available post types are: offer, wanted

NOTE: Additional post types may be added in the future (eg. events) so clients should take care to support arbitrary types being returned. items: type: string send_count: type: integer description: The number of time the alert has triggered and been send out. last_sent: type: string format: date-time description: The UTC date and time when the alert was last triggered and sent out (may be null). example: alert_id: 7584 user_id: 9191 search: table types: - offer send_count: 3 last_sent: "2018-02-16T12:58:51" # TODO: client needs to implement support for group notices for TN groups.. GroupNotice: description: Group notices are created by group moderators in order to provide useful information to the group members (eg. group rules and guidelines). type: object properties: notice_id: type: string group_id: type: string date: type: string format: date-time description: The UTC date and time when this notice was received. title: type: string content: type: string example: notice_id: 81178 group_id: 1781 date: "2018-02-17T13:22:40" title: Group Rules & Guidelines content: Everything must be free, legal and appropriate for all ages. Repeat offenders will be banned. Group: description: > Groups are run by volunteer moderators and provide a way to group activity in a specific location. Because each group is usually run by different people, there can be variations in rules from group to group (eg. who is allowed to join, what is allowed to be posted, how often reposts are allowed). type: object properties: group_id: type: string name: type: string description: The name of the group (not guaranteed to be unique). identifier: type: string description: A unique identifier for the group that is used in URLs. homepage: type: string description: A URL to the group homepage. member_count: type: integer description: The number of members who belong to the group. latitude: type: number longitude: type: number timezone: type: string description: The timezone that the group is in (eg. America/New_York). # open_membership: type: boolean description: When true, the group allows anyone to join. When false, the group moderators review and approve applicants. open_archives: type: boolean description: When true, the group posts are viewable by anyone. When false, the group posts can only be viewed by members of the group. has_questions: type: boolean description: When true, anyone requesting membership to this group will be required to answer a new membership questionnaire. country: type: object description: Provides information about the country that is associated with a group. May be null. properties: name: type: string description: The name of the country. abbreviation: type: string description: > A 2 letter country code for the country (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ). example: name: United States abbreviation: US region: type: object description: Provides information about an area within a country that a group is associated with (eg. a state in the US or a province in Canada). May be null. properties: name: type: string description: The name of the region. abbreviation: type: string description: A 2 letter abbreviation for the region (is not guaranteed to be globally unique but is unique among all the regions in the country). example: name: California abbreviation: CA membership: type: object description: > Provides information about the current users' active or pending membership to this group (if any). Will be null if there is no active or pending membership to this group. properties: status: type: string description: > One of: subscribed, pending, pending-questions date: type: string format: date-time description: > The UTC date and time when the membership was last updated. questionnaire: type: object description: Membership questionnaire data. Will be null unless the membership status is pending-questions. properties: message: type: string description: A message from the group moderators to be displayed above the questions (may be null). questions: type: array description: The list of questions. items: type: string example: group_id: 46 name: Ottawa Reuse identifier: OttawaReuse homepage: https://trashnothing.com/OttawaReuse member_count: 4838 latitude: 45.423494 longitude: -75.697933 timezone: America/Toronto open_membership: false open_archives: false has_questions: true country: name: Canada abbreviation: CA region: name: Ontario abbreviation: ON membership: status: pending-questions date: "2015-01-22T17:05:50" questionnaire: message: This group is only for people who live in Ottawa. questions: - Where do you live? Feedback: type: object properties: feedback_id: type: string user_id: type: string description: The user ID of the user that the feedback is about. reviewer_user_id: type: string description: The user ID of the user that submitted the feedback. content: type: string description: A comment written by the reviewer about the user (may be null). positive: type: boolean description: Set to true for positive feedback and false for negative feedback. date: type: string format: date-time description: Date when the feedback was submitted. example: user_id: 2946512 reviewer_user_id: 9191 content: Fred gave me a great antique table for my new apartment! positive: true date: "2020-03-01T12:01:22" User: type: object properties: user_id: type: string username: type: string description: > A username that can be displayed for the user (the username is NOT guaranteed to be unique). Will be null for api key requests and requests where the oauth user doesn't belong to any of the same groups as this user. country: type: string description: > A 2 letter country code for the country that has been automatically detected for the user (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ). May be null if no country has been set. profile_image: type: string description: > A URL to a profile image for the user. Profile images sizes vary based on the source (Google, Facebook, Gravatar, etc) and some can be as small as 64px by 64px. Will be null for api key requests and requests where the oauth user doesn't belong to any of the same groups as this user. member_since: type: string description: The date and time when the user first became publicly active on a group (the date may be older than when the user signed up). firstname: type: string description: The first name of the user (may be null). lastname: type: string description: The last name of the user (may be null). reply_time: type: integer description: > An estimate of how many seconds it takes this user to reply to messages. May be null when there is not enough data to calculate an estimate. feedback: type: object properties: restriction: type: string description: > If the current user can leave positive or negative feedback on this user then restriction is null.

Otherwise, restriction is set to a string that explains why feedback is currently restricted and what type of feedback is restricted. The string will be one of the following: no-recent-messages, negative-score, moderator, [days]-day-wait-for-negative

- **no-recent-messages**: The current user has not received any messages from this user in the last 30 days.
- **negative-score**: The current user has a negative feedback and will not be able to leave feedback until their score is >= 0.
- **moderator**: The user is a moderator and leaving feedback on moderators is not currently supported.
- **[days]-day-wait-for-negative**: Positive feedback is not restricted but the current user must wait some number of days before they will be able to leave negative feedback on this user. This string can change depending on the number of days. For example, when the current user must wait one day, the string will be '1-day-wait-for-negative'. A wait is necessary because a lot of negative feedback results from communication issues that are resolved with more time. score: type: integer description: > The feedback score of this user. Higher scores are better. Scores are calculated by substracting the total number of negative feedback from the total number of positive feedback that a user has received. May be null if a user has not received enough feedback to calculate a score. percent_positive: type: number description: > The percent of feedback that this user has received in the last year that was positive. May be null if a user has not received enough feedback to calculate a percentage. minimum: 0 maximum: 100 about_me: type: string description: > A short bio a user has written about themselves to help other members get to know them better. May be null if the user has not written anything about themselves. example: user_id: 2946512 username: fred gibson country: GB profile_image: https://lh3.googleusercontent.com/-1qVLzuOCyYg/AAAAAAAAAAI/AAAAAAAAAAA/0aGNzRAO61c/s64-c/100783935580725962164.jpg member_since: "2017-01-27T06:35:55" firstname: null lastname: null reply_time: 4850 feedback: restriction: no-recent-messages score: 7 percent_positive: 87.5 about_me: Just an old fisherman looking to reuse more. CurrentUser: allOf: - $ref: "#/definitions/User" - type: object properties: public_name: type: boolean description: Whether or not the user has chosen to make their first and last name public. verified: type: boolean description: > Whether or not the user has verified their account. The user account will be limited (eg. they will not be able to reply to posts) until their account is verified. has_password: type: boolean description: > Whether or not the user has a password (accounts created using 3rd party providers like Facebook don't have passwords set).

When has_password is false, the only way to set a password on the users' account is to send the user a password reset email. email: type: object description: Data related to the users' email address. properties: address: type: string description: The email address. bouncing: type: boolean description: > Whether or not this email address has been bouncing emails that are sent to it. When bouncing is true, no emails will be sent to the user. If the user thinks that their email account shouldn't be bouncing emails, use the email not bouncing endpoint to reset bouncing to false. spam_stop: type: boolean description: > Whether or not emails have been stopped because of a spam complaint from the users' email account. When spam_stop is first set to true, it indicates that all emails have been automatically disabled for the users' account (eg. digest and alerts). The user will need to re-enable digests and re-add any alerts that they had previously set up. uses_fair_offer_policy: type: boolean description: Whether or not the user used the Fair Offer Policy (see https://trashnothing.com/fair_offer_policy ) the last time they posted. email_posts_frequency: type: string description: > How often new post email notifications are sent to the user. One of: weekly, twice_weekly, daily, 12_hours, 8_hours, 6_hours, 4_hours, 2_hours, hourly

Will be null if new post email notifications are turned off. digest_photos: type: boolean description: Whether or not photos are included in the digest emails sent to the user. email_post_reminders: type: boolean description: Whether or not post reminder emails are enabled for this user (to remind them to update or repost their posts). email_search_alerts: type: boolean description: Whether or not search alert emails are enabled for this user. email_message_delay: type: string description: > How quickly new messages from other users are emailed to this user. One of: immediate, 30_minutes, 1_hour, 2_hours, 4_hours, 6_hours, 8_hours
If set to anything other than immediate, the user will receive a digest email summarizing all of the new messages that they haven't viewed. special_notices: type: boolean description: > Whether or not the user wants to receive special notice emails from the groups they are a member of. Special notices are admin posts that the group moderators choose to send out by email. signup: type: string format: date-time description: The UTC date and time when the user signed up. profile_image_source: type: string description: > The source of the users' profile image. One of: gravatar, facebook, google, freegle, custom last_listings_view: type: string format: date-time description: > The UTC date and time when the user last viewed the newest posts on the All Posts page (may be null).

NOTE: For this to be accurate, clients must update the last_listings_view property of the current user every time the user is shown the newest posts on the All Posts page. location: type: object description: The users' location. The location is used to determine which posts are shown to the user (may be null). properties: name: type: string description: A text description of the location specified by latitude and longitude. latitude: type: number longitude: type: number radius: type: number description: Defines the radius (in meters) of a circle around the point specified by latitude and longitude. minimum: 0 maximum: 257500 public_post_sources: type: array description: > A list of the public post sources the user is interested in seeing posts from (currently only 'trashnothing' is supported). If the array is empty, no sources are enabled and the user will only see posts from the groups they are a member of.

NOTE: Additional sources may be added in the future so clients should take care to support arbitrary sources being returned. items: type: string show_all_group_posts: type: boolean description: > If true, all group posts from the users' groups are shown to them on the main posts page and in the digests.

If false, only group posts in the area defined by the users' location are shown. example: user_id: 119458 username: captainjack country: US profile_image: https://gravatar.com/avatar/88305a95b05b30f6cd306019ea5d88f3?s=90&r=pg&default=identicon member_since: "2009-09-25T14:20:01" firstname: Jack lastname: Carter about_me: I used to be an accountant but then I decided to become a pirate. public_name: false verified: true has_password: false email: address: johndoe@example.com verified: true bouncing: false spam_stop: false uses_fair_offer_policy: true email_posts_frequency: 6_hours digest_photos: false show_all_group_posts: true email_post_reminders: true email_search_alerts: true email_message_delay: immediate special_notices: true signup: "2017-11-20T04:32:06" profile_image_source: gravatar last_listings_view: "2018-02-15T15:04:47" location: name: Wheat Ridge, CO, USA latitude: 39.766098 longitude: -105.077206 radius': 32186.88 public_post_sources: # - trashnothing #