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.2" title: trash nothing termsOfService: > https://trashnothing.com/terms host: trashnothing.com basePath: /api/v1.2 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: digest in: formData description: > The frequency of digest emails sent to this user. One of: weekly, twice_weekly, daily, 12_hours, 8_hours, 6_hours, 4_hours, 2_hours, hourly

To disable digests, 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: post_reminders in: formData description: > Whether or not the user will receive post reminder emails (to remind them to update or repost their posts). Set to 1 to enable and 0 to disable. 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 digest emails. 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 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. 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. # 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. 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. # 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, 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** - The user showed up later than they said they would.
**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: true 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. 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.

NOTE: An alternate way to submit posts that does quicker client side validation is to use the script served by the API at the /posts/client.js endpoint (see the description of the /posts/client.js endpoint for usage instructions). 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. 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. 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" # deprecated geolocate_bounds: $ref: "#/definitions/GeolocateBounds" description: (DEPRECATED) 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: array items: $ref: "#/definitions/Post" 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}/flag: post: tags: - posts summary: Flag a post description: Flags a post to be reviewed by the moderators. operationId: flag_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 flagged. 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 flagging 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 flagged. 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. /posts/client.js: get: tags: - posts summary: Retrieve client.js description: | Defines javascript functions that can be used to validate and submit posts. The advantage of using these functions versus using the post submission endpoint directly is that some of the post validation checks can be done on the client side which will be faster. NOTE: If used, this javascript file MUST be loaded dynamically for each user because the contents of the file are generated dynamically based on the current user. The file may be cached on a per user basis based on the HTTP cache headers that are returned when the file is requested (currently the cache headers specify that the file should expire after one day). The following functions are available: --- **window.TN.check_crossposting_restrictions(group_ids)** Checks for crossposting restrictions when the user selects more than one group to post to. Parameters: - **group_ids** is an array of group IDs Returns an object with three properties {allowed, restricted, restrictions}. - **allowed** is an array of the group IDs from group_ids that can be crossposted to - **restricted** is an array of the group IDs from group_ids that can't be crossposted to - **restrictions** is an object mapping group IDs that have crossposting restrictions to arrays of group IDs that are restricted. It is useful for pinpointing why a group ID shows up in the restricted array so that users can be provided feedback about the reason for the crossposting restriction (eg. a message like 'group A doesn't allow crossposting to group B'). For example, given group_ids = [1, 2, 3, 4] and assuming group 1 doesn't allow posting to group 3 and group 2 doesn't allow posting to group 1, the returned object will be: {allowed: [4], restricted: [1, 2, 3], restrictions: {1: [3], 2: [1]}} --- **window.TN.submit_post(args, session, preferences, callback)** Submits a new post and performs validation checks on the post before it is accepted for submission. Parameters: - **args** is an object containing data about the post being submitted and must include the following properties: - type: The type of post. One of: offer, wanted - title: A short description of the item(s). - location: A short location description. The following properties are optional: - content: A longer description of the item(s). - group_ids: An array of group IDs to submit the post to (if any). - fair_offer: 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 ). - photo_ids: A comma separated list of the IDs of the photos that should be attached to this post. - latitude - longitude - **session** is a temporary object that is used by submit_post to store data about the submission process for a single post. The first time submit_post is called with a post, session should be a new empty object (eg. {}). The session object should be persisted 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. - **preferences** is a permanent object that the client persists and modifies based on warnings returned by the post submission process and user input. Some post warnings passed to the callback object 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 only read by submit_post and never modified - it is up to the client to initialize, modify and persist the preferences object. - **callback** is a function used to return the result of the post submission. It is called and passed one argument - an object with five properties {result, message, preference_key, identifier, session}. The result property is a string that is one of: success, error, warning. The identifier property is set for errors and warnings and will contain a string that represents the type of error or warning that occurred. A success result indicates that the post was submitted successfully. Note that posts may not appear instantly after submission because the moderators of many groups may have additional automatic or manual review processes in place that can delay the publishing of a post. An error result indicates that there is an error with the post to show 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 the post (with the updated session object) to temporarily override that specific warning. 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). operationId: get_post_client_javascript produces: - text/javascript parameters: - name: group_ids in: query description: > A comma separated list of all the group IDs that the current user is a member of. If the current user is not a member of any groups, simply pass an empty string. required: true type: string - name: callback in: query description: The name of a global function to call once the script is loaded. required: false type: string - name: access_token in: query description: > Passing the current users' OAuth2 access token as a GET parameter makes it easier to load this script in a normal HTML