# Fetch one group, with its steps and files

- Endpoint: `GET /v1/{organizationId}/group-challenge/{challengeId}/group/{groupId}`
- Production: `https://api.main-team.org/v1/{organizationId}/group-challenge/{challengeId}/group/{groupId}`
- Sandbox: `https://apisnd.main-team.org/v1/{organizationId}/group-challenge/{challengeId}/group/{groupId}`
- Operation: `getGroupChallengeGroup` (Group challenges)
- Authentication: `Authorization: Bearer <token>`, a short-lived token you sign with your API key and secret
- Permission: `group-challenge/read:$org:$ID`

## Description

Reads one group that one of your students is an active member of, with each step, its state and its files. Steps appear once the teacher has confirmed the group (`finalized`).

`canSubmit` on a step and `canFinalSubmit` on the group are the answers `submitGroupChallengeStep` and `submitGroupChallengeWork` would give right now, so read the group before you submit.

Only your own students are named. Every other person — the other members, the teacher, the organizers — is shown by role alone, with `studentId` and `name` set to `null`, and a file’s name only when one of your students uploaded it.

## Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `organizationId` | path | yes | string | The organization’s `_id`: 24 hexadecimal digits, as `listOrganizations` (`GET /v1/organization`) lists it. |
| `challengeId` | path | yes | string | The group challenge’s `_id`, from `listGroupChallenges`. |
| `groupId` | path | yes | string | The group’s `_id`, from `listGroupChallengeGroups` or a student’s `group`. |

## Response

`200` Success: `message` is "Group fetched successfully.".

```json
{
  "success": true,
  "message": "Group fetched successfully.",
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 57,
    "totalPages": 3
  },
  "data": {
    "_id": "6650a1b2c3d4e5f6a7b8c9ed",
    "challengeId": "6650a1b2c3d4e5f6a7b8c9eb",
    "shortCode": "7KQ2MX",
    "name": null,
    "displayName": "Group 7KQ2MX",
    "status": "finalized",
    "gradeGroup": {
      "_id": "6650a1b2c3d4e5f6a7b8c9ec",
      "label": "Group 7-8-9"
    },
    "memberCount": 3,
    "yourStudents": [
      {
        "studentId": "6650a1b2c3d4e5f6a7b8c9d0",
        "firstName": "Ada",
        "lastName": "Lovelace",
        "gradeName": "8",
        "addedAt": "2026-10-05T13:20:00.000Z"
      }
    ],
    "stepCount": 3,
    "stepsSubmitted": 1,
    "createdAt": "2026-10-05T13:20:00.000Z",
    "finalizedAt": "2026-10-12T08:15:00.000Z",
    "finalSubmittedAt": null,
    "finalSubmittedBy": {
      "role": "student",
      "studentId": "6650a1b2c3d4e5f6a7b8c9d0",
      "name": "Ada Lovelace",
      "yours": true
    },
    "canFinalSubmit": false,
    "steps": [
      {
        "_id": "6650a1b2c3d4e5f6a7b8c9ee",
        "order": 1,
        "title": "Project proposal",
        "state": "submitted",
        "openedAt": "2026-10-12T08:15:00.000Z",
        "submittedAt": "2026-10-20T16:02:11.000Z",
        "submittedBy": {
          "role": "student",
          "studentId": "6650a1b2c3d4e5f6a7b8c9d0",
          "name": "Ada Lovelace",
          "yours": true
        },
        "reopenCount": 0,
        "canSubmit": false,
        "files": [
          {
            "_id": "6650a1b2c3d4e5f6a7b8c9ef",
            "status": "submitted",
            "name": "proposal.pdf",
            "fileType": "pdf",
            "size": 1048576,
            "uploadedBy": {
              "role": "student",
              "studentId": "6650a1b2c3d4e5f6a7b8c9d0",
              "name": "Ada Lovelace",
              "yours": true
            },
            "completedAt": "2026-10-20T15:47:03.000Z",
            "submittedAt": "2026-10-20T16:02:11.000Z"
          }
        ]
      }
    ]
  }
}
```

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | [`bad_request`](https://hub.main-team.org/api/errors#bad_request) | `challengeId` is not 24 hexadecimal digits. |
| 400 | [`bad_request`](https://hub.main-team.org/api/errors#bad_request) | `groupId` is not 24 hexadecimal digits. |
| 401 | [`unauthorized`](https://hub.main-team.org/api/errors#unauthorized) | The token is missing or malformed, is not signed with your account’s `apiSecret`, breaks the `iat` and `exp` rules, has expired or been revoked, or its account is not active. All of these answer the same. |
| 403 | [`forbidden`](https://hub.main-team.org/api/errors#forbidden) | The token is valid, but no role on your account allows `group-challenge/read` on the organization in the path, or a role denies it. |
| 404 | [`not_found`](https://hub.main-team.org/api/errors#not_found) | `organizationId` is not the `_id` of an organization. |
| 404 | [`not_found`](https://hub.main-team.org/api/errors#not_found) | Group challenges are not switched on for this organization. The answer is the one an unknown path gets; nothing was read. |
| 404 | [`not_found`](https://hub.main-team.org/api/errors#not_found) | No group challenge of this organization has this id, or it is not published: a draft, archived or deleted challenge answers the same. |
| 404 | [`not_found`](https://hub.main-team.org/api/errors#not_found) | No group of this challenge has this id that one of your students is an active member of: a missing group, a deleted one and another account’s get the same answer. |
| 429 | [`too_many_requests`](https://hub.main-team.org/api/errors#too_many_requests) | Your account has made more than 100 requests to this operation in the current 60-second window. Wait the seconds in `Retry-After` before sending again. |
| 500 | [`internal_error`](https://hub.main-team.org/api/errors#internal_error) | Something failed on our side. Retry later, and quote `request_id` if it goes on. |

## Code samples

### curl

```bash
# $TOKEN: a short-lived token you minted with your API key and secret
curl -sS 'https://api.main-team.org/v1/<organizationId>/group-challenge/<challengeId>/group/<groupId>' \
  -H "Authorization: Bearer $TOKEN"
```

### Node.js

```js
const token = process.env.TOKEN; // a short-lived token you minted with your API key and secret

const res = await fetch('https://api.main-team.org/v1/<organizationId>/group-challenge/<challengeId>/group/<groupId>', {
  headers: {
    Authorization: `Bearer ${token}`,
  },
});
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`);
console.log(body.data);
```

### PHP

```php
<?php
$token = getenv('TOKEN'); // a short-lived token you minted with your API key and secret

$ch = curl_init('https://api.main-team.org/v1/<organizationId>/group-challenge/<challengeId>/group/<groupId>');
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $token,
    ],
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$body = json_decode($response, true);
if ($status >= 400) {
    $error = $body['error'];
    throw new RuntimeException("$status {$error['code']}: {$error['message']}");
}
print_r($body['data']);
```
