> ## Documentation Index
> Fetch the complete documentation index at: https://apidocs.hopnow.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Submit Agreement Actions

> Accept or reject one or more of a virtual account group's agreements in a single batch

This endpoint works on any account you own. [Create Virtual Account Group](/fx/api-reference/virtual-account-groups/create-group) covers who can open a group and what the account needs first.

Records the account holder's decision on the agreements listed by [List Agreements](/fx/api-reference/virtual-account-groups/list-agreements). Onboarding completes when every agreement is accepted and every document requirement is satisfied.

The batch is validated as a whole before anything is sent to the provider: if any agreement in it is not `pending`, has expired, or is being rejected while `declinable` is `false`, the request fails with `409` and nothing is applied.

A `200` does **not** mean every action was accepted. Hop forwards the batch to the provider and returns one entry per requested action in `results`. An entry with a non-null `error` failed and its agreement is unchanged, still `pending`, while the other entries in the same response may have succeeded. Always inspect every entry; never treat the status code alone as success.

After the call, Hop resumes the group's onboarding in the background, so the group's requirements and onboarding status update shortly afterwards. Poll [Get Virtual Account Group](/fx/api-reference/virtual-account-groups/get-group) for the new state.

Requires an API key with `write` access on the `virtual_accounts` scope.

## Path Parameters

<ParamField path="account_id" type="string" required>
  The account's external ID (starts with `acct_`)
</ParamField>

<ParamField path="group_id" type="string" required>
  The virtual account group's external ID (starts with `vag_`). It must belong to the account in the path.
</ParamField>

## Headers

<ParamField header="Idempotency-Key" type="string" required>
  Canonical lowercase 8-4-4-4-12 UUID. Scoped to the group, with the payload fingerprinted: replaying the same key with the same payload returns the recorded outcome, and with a different payload returns `409`. See [Idempotency](/fx/api-reference/idempotency).
</ParamField>

## Request Body

<ParamField body="agreement_actions" type="array" required>
  The decisions to submit, 1 to 50 entries. Each `agreement_id` must appear at most once and must belong to the group in the path.

  <Expandable title="Action Fields">
    <ParamField body="agreement_id" type="string" required>
      Agreement to act on (starts with `agr_`), from [List Agreements](/fx/api-reference/virtual-account-groups/list-agreements)
    </ParamField>

    <ParamField body="action" type="string" required>
      `accept` or `reject`. `reject` is only permitted when the agreement's `declinable` is `true`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="signer_id" type="string">
  The authorised associated person signing on behalf of a business account (starts with `aap_`, must belong to the account and carry `is_signer: true`). Required for a business account and rejected for an individual one, which has no associated persons and signs as itself. See [Create Associated Person](/fx/api-reference/associated-persons/create-associated-person).
</ParamField>

## Response

Returns `200` with one entry per requested action, in the same order as `agreement_actions`.

<ResponseField name="results" type="array">
  Per-action outcomes

  <Expandable title="Result Fields">
    <ResponseField name="agreement_id" type="string">
      The agreement this entry is about (starts with `agr_`)
    </ResponseField>

    <ResponseField name="status" type="string">
      The agreement's new status, `accepted` or `rejected`, on a successful entry. `null` when `error` is set.
    </ResponseField>

    <ResponseField name="responded_at" type="string">
      ISO 8601 timestamp when the decision was recorded, on a successful entry. `null` when `error` is set.
    </ResponseField>

    <ResponseField name="error" type="string">
      Why this action failed, as reported by the provider, or `null` on success. A non-null value is the only signal that this entry failed: its agreement stays `pending` and the decision was not recorded.
    </ResponseField>
  </Expandable>
</ResponseField>

### Retrying a partial failure

Retry by sending the same batch again with the **same** `Idempotency-Key`. Entries already recorded under that key are exempt from the `pending` check, and the batch reaches the provider under the same key, so only the entries that failed are acted on again.

A fresh key on the same batch is rejected with `409`, because the agreements that succeeded the first time are no longer `pending`. Use a fresh key only for a batch of agreements you have not acted on yet.

## Errors

| Status | `code` | When |
| - | - | - |
| `404` | `RESOURCE_NOT_FOUND` | `group_id`, an `agreement_id` or `signer_id` is unknown or belongs to another account or group |
| `409` | `BUSINESS_RULE_VIOLATION` | An agreement in the batch is not `pending` (`details` carry `agreement_id` and `status`), has passed its `expires_at`, or is being rejected while `declinable` is `false`; or the `Idempotency-Key` was already used with a different payload. Nothing in the batch is applied. |
| `422` | `BUSINESS_RULE_VIOLATION` | `signer_id` was omitted for a business account or sent for an individual account, the person is not marked as a signer, or the batch contains the same `agreement_id` twice |
| `422` | `VALIDATION_ERROR` | `Idempotency-Key` is missing or not a canonical 8-4-4-4-12 UUID, `agreement_actions` is empty or over 50 entries, or `action` is not `accept` or `reject` |
| `502` | `GATEWAY_ERROR` | The provider call failed outright, so no decision was recorded. Retry with the same key. A provider failure on a single agreement is reported in that entry's `error` with `200` instead. |

## Request Example

```bash theme={null}
curl -X POST "https://api.hopnow.io/v1/accounts/acct_ka44qsvpo8q3wtzuwfqf0h6u/virtual-account-groups/vag_7m2k9x4c1b6v3n8q5z0j2p7t/agreements/actions" \
  -H "X-API-Key: your_api_key" \
  -H "X-Signature: hmac_signature" \
  -H "X-Timestamp: 1234567890" \
  -H "X-Nonce: abc123" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "signer_id": "aap_5r8t1v4x6z0b3n5q7w2e9y4u",
    "agreement_actions": [
      {"agreement_id": "agr_3f8k1m5p9r2t6v4x7z0b3n5q", "action": "accept"},
      {"agreement_id": "agr_g738im3ueie9s9zexmf9cl87", "action": "accept"}
    ]
  }'
```

## Response Example

```json theme={null}
{
  "results": [
    {
      "agreement_id": "agr_3f8k1m5p9r2t6v4x7z0b3n5q",
      "status": "accepted",
      "responded_at": "2026-01-16T09:12:00Z",
      "error": null
    },
    {
      "agreement_id": "agr_g738im3ueie9s9zexmf9cl87",
      "status": null,
      "responded_at": null,
      "error": "Agreement is awaiting a new version and cannot be signed"
    }
  ]
}
```
