# List resources

Returns the approved community resources your key is allowed to see, newest first: food, housing, health and other support that organizations on Bynefit publish for their communities. Use it to show a local directory or keep a copy in sync.

## Request

| Request |  |
| --- | --- |
| Method and path | `GET /dash/api/v1/resources` |
| Needs | A key that can read resources, sent as a bearer token |
| Permission | `read:resources:public` |

## Parameters

| Name | Type | What it does |
| --- | --- | --- |
| `category` | string | Filter by slug: `food`, `housing`, `health`, `employment`, `education`, `childcare`, `legal`, `mental`, `transport`, `finance`, `community`, `other`. An unrecognized value is ignored. |
| `since` | ISO-8601 date-time | Only entries registered at or after this moment, e.g. `2026-01-01T00:00:00Z`. An unparseable value returns `400` with `invalid_since`. |
| `limit` | integer | Entries per page. Defaults to 50; values above 200 are capped at 200. |
| `cursor` | string | The `next_cursor` from the previous page. Omit it to start from the newest entry. A malformed cursor returns `400` with `invalid_cursor`. |
| `offset` | integer | Skip this many entries, from 0 to 10000. An alternative to `cursor` for callers that page by position. Do not send both, or you get `400` with `invalid_paging`. Anything else returns `400` with `invalid_offset`. |
| `sort` | string | `newest` (the default) or `popular`, most upvoted first. `popular` pages with `offset`, not `cursor`. Anything else returns `400` with `invalid_sort`. |

## Example

**cURL**

```bash
curl "https://bynefit.com/dash/api/v1/resources?category=food&limit=5" \
  -H "Authorization: Bearer bapi_pk_your_key_here"
```

**JavaScript**

```javascript
const url = new URL('https://bynefit.com/dash/api/v1/resources');
url.searchParams.set('category', 'food');
url.searchParams.set('limit', '5');

const res = await fetch(url, {
  headers: { Authorization: 'Bearer bapi_pk_your_key_here' },
});
const { data, next_cursor, has_more } = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    'https://bynefit.com/dash/api/v1/resources',
    params={'category': 'food', 'limit': 5},
    headers={'Authorization': 'Bearer bapi_pk_your_key_here'},
)
body = res.json()
rows, cursor, more = body['data'], body['next_cursor'], body['has_more']
```

**PHP**

```php
$query = http_build_query(['category' => 'food', 'limit' => 5]);
$ch = curl_init('https://bynefit.com/dash/api/v1/resources?' . $query);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer bapi_pk_your_key_here'],
    CURLOPT_RETURNTRANSFER => true,
]);
$body = json_decode(curl_exec($ch), true);
$rows = $body['data'];
```

**Swift**

```swift
var parts = URLComponents(string: "https://bynefit.com/dash/api/v1/resources")!
parts.queryItems = [
    URLQueryItem(name: "category", value: "food"),
    URLQueryItem(name: "limit", value: "5"),
]
var req = URLRequest(url: parts.url!)
req.setValue("Bearer bapi_pk_your_key_here", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: req)
```

## Response

**200 OK (application/json)**

```json
{
  "data": [
    {
      "id": "res_3f9a1c07d2b84e55",
      "byn_id": "3f9a1c07d2b84e55",
      "type": "resource",
      "name": "Atlanta Community Food Bank",
      "description": "Food distribution for metro Atlanta",
      "category": "food",
      "address": "732 Joseph E. Lowery Blvd NW, Atlanta, GA",
      "phone": "(404) 892-9822",
      "website": "https://www.acfb.org",
      "hours": null,
      "upvote_count": 4,
      "go_website": "https://bynefit.com/go/r101w",
      "go_phone": "https://bynefit.com/go/r101p",
      "registered_on": "2026-04-21T19:45:02+00:00"
    }
  ],
  "count": 1,
  "total": 212,
  "next_cursor": "eyJjIjoiMjAyNi0wNC0yMSAxOTo0NTowMiIsImkiOjEwMX0",
  "has_more": true,
  "meta": {
    "source": "bynefit.com",
    "powered_by": "Bynefit Inc.",
    "license": "Public domain — free to use with attribution",
    "docs": "https://bynefit.com/docs/resources-read"
  }
}
```

## Paging

Entries come back newest first. While `has_more` is `true`, request the next page by passing `next_cursor` back as `cursor`, keeping your other filters the same. On the last page `has_more` is `false` and `next_cursor` is `null`. Treat the cursor as an opaque string — don't build or parse it. `count` is how many entries are in this page, and `total` is how many match your filters across every page. `total` reads `"10000+"` when more than 10,000 match, and is left out when you page with `offset`, so use `has_more` to know when to stop.

**curl (next page)**

```bash
curl "https://bynefit.com/dash/api/v1/resources?category=food&limit=5&cursor=NEXT_CURSOR" \
  -H "Authorization: Bearer bapi_pk_…"
```

## Fields

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | Stable opaque identifier, prefixed `res_`. |
| `byn_id` | string | The same identifier without the prefix. |
| `type` | string | Always `resource`. |
| `name` | string | Display name of the resource. |
| `description` | string | Short description of what it does. |
| `category` | string | One of the category slugs above. |
| `address` | string | Single-line street address. |
| `phone` | string | Contact phone as entered by the publisher. |
| `website` | string | Public URL. Can be empty. |
| `hours` | string | Free-text hours. Can be empty. |
| `upvote_count` | integer | How many people have upvoted the entry. |
| `go_website`, `go_phone` | string | Tracked short links that open the entry's website or dial its phone. `null` when the entry has none. |
| `registered_on` | string | ISO-8601 time the entry was added. |

## Errors

| Status and code | Meaning |
| --- | --- |
| `400 invalid_since` | `since` is not an ISO-8601 date-time. |
| `400 invalid_paging`, `invalid_offset`, `invalid_sort` | The paging or sort parameters are not allowed together, or not valid on their own. See Parameters. |
| `400 invalid_cursor` | The cursor was not issued by this API. Start again without one. |
| `401` | The key is missing, wrong or revoked. |
| `429` | Too many requests. Wait for the time in `Retry-After`. |

> **Only approved entries are returned.** Submissions still in review are not exposed on this endpoint. See [Resources — submit](https://bynefit.com/docs/resources-submit) if you want to contribute a new entry.

> **Moving from the older `?key=` endpoint?** It was switched off on 11 October 2026; use the endpoint on this page. See [Migrating from the legacy endpoint](https://bynefit.com/docs/legacy-sunset).

> **Rate limits.** Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (a Unix timestamp). A `429` includes `Retry-After` in seconds.

---

Source: https://bynefit.com/docs/resources-read
Checked against the live API on October 10, 2026.
