# zone.stratos.space.getSpaceCredential

> Published by [lexicon.northsky.app](https://lexicon.garden/identity/did:plc:6uxgo3ypovauub7nblwylqyv)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:6uxgo3ypovauub7nblwylqyv/zone.stratos.space.getSpaceCredential)
- [Documentation](https://lexicon.garden/lexicon/did:plc:6uxgo3ypovauub7nblwylqyv/zone.stratos.space.getSpaceCredential/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:6uxgo3ypovauub7nblwylqyv/zone.stratos.space.getSpaceCredential/examples)

## Definitions

### `zone.stratos.space.getSpaceCredential`

**Type**: `procedure`

Issue a space credential (JWT) for a space the caller is a member of. The credential is multi-use until it expires and is bound to the caller's DPoP key (cnf.jkt, RFC 9449): it must be presented under the DPoP auth scheme with a per-request proof signed by that key. It is signed by the space authority's signing key so any repo host can verify it without contacting the authority. Identity is resolved from a delegation token when provided (a standalone DPoP proof in the DPoP header supplies the key to bind), otherwise from the DPoP-authenticated user (the session proof key is bound). Membership is checked live against the enrollment store. App-axis (client attestation) gating is enforced here: spaces configured with an app allow-list require a valid client attestation whose attested client_id is listed; spaces that are open ignore any attestation supplied.

#### Input

**Encoding**: `application/json`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `space` | `string` | Yes | The space's at:// URI (at://{did}/space/{type}/{skey}). Mirrors the upstream space-ref string format (atproto#5187); declared as a plain string until @atproto/lexicon supports that format. Its space DID must equal this service's DID. |
| `delegationToken` | `string` | No | Optional space-delegation JWT. When present, the caller's identity is taken from this token (its target space must equal `space`) instead of the DPoP session. |
| `clientAttestation` | `string` | No | Optional client-attestation JWT (an OAuth private_key_jwt client assertion to the space authority). Required only for spaces gated on client app identity (appAccess allowList); the allow-list is evaluated against the attested client_id. Ignored for open spaces. |

#### Output

**Encoding**: `application/json`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `expiresAt` | `string` (datetime) | Yes | The credential's expiry time (matches the JWT `exp` claim). |
| `credential` | `string` | Yes | The compact-serialized space-credential JWT. |

#### Errors

- **InvalidToken**: The supplied delegation token failed verification, or its target space does not match the requested space.
- **NotEnrolled**: The identified user is not enrolled in the boundary corresponding to the requested space.
- **UnknownSpace**: The requested space URI is malformed or its space DID does not match this service's DID.
- **AttestationRequired**: The requested space gates on client app identity (appAccess allowList) but no valid client attestation was supplied.
- **ClientNotAllowed**: A valid client attestation was supplied but its attested client_id is not in the space's app allow-list.
- **ProofRequired**: No DPoP key was available to bind the credential to: the delegation path requires a standalone DPoP proof in the DPoP header, and unbound credentials are refused outside development mode.

## Raw Schema

```json
{
  "id": "zone.stratos.space.getSpaceCredential",
  "defs": {
    "main": {
      "type": "procedure",
      "input": {
        "schema": {
          "type": "object",
          "required": [
            "space"
          ],
          "properties": {
            "space": {
              "type": "string",
              "description": "The space's at:// URI (at://{did}/space/{type}/{skey}). Mirrors the upstream space-ref string format (atproto#5187); declared as a plain string until @atproto/lexicon supports that format. Its space DID must equal this service's DID."
            },
            "delegationToken": {
              "type": "string",
              "description": "Optional space-delegation JWT. When present, the caller's identity is taken from this token (its target space must equal `space`) instead of the DPoP session."
            },
            "clientAttestation": {
              "type": "string",
              "description": "Optional client-attestation JWT (an OAuth private_key_jwt client assertion to the space authority). Required only for spaces gated on client app identity (appAccess allowList); the allow-list is evaluated against the attested client_id. Ignored for open spaces."
            }
          }
        },
        "encoding": "application/json"
      },
      "errors": [
        {
          "name": "InvalidToken",
          "description": "The supplied delegation token failed verification, or its target space does not match the requested space."
        },
        {
          "name": "NotEnrolled",
          "description": "The identified user is not enrolled in the boundary corresponding to the requested space."
        },
        {
          "name": "UnknownSpace",
          "description": "The requested space URI is malformed or its space DID does not match this service's DID."
        },
        {
          "name": "AttestationRequired",
          "description": "The requested space gates on client app identity (appAccess allowList) but no valid client attestation was supplied."
        },
        {
          "name": "ClientNotAllowed",
          "description": "A valid client attestation was supplied but its attested client_id is not in the space's app allow-list."
        },
        {
          "name": "ProofRequired",
          "description": "No DPoP key was available to bind the credential to: the delegation path requires a standalone DPoP proof in the DPoP header, and unbound credentials are refused outside development mode."
        }
      ],
      "output": {
        "schema": {
          "type": "object",
          "required": [
            "credential",
            "expiresAt"
          ],
          "properties": {
            "expiresAt": {
              "type": "string",
              "format": "datetime",
              "description": "The credential's expiry time (matches the JWT `exp` claim)."
            },
            "credential": {
              "type": "string",
              "description": "The compact-serialized space-credential JWT."
            }
          }
        },
        "encoding": "application/json"
      },
      "description": "Issue a space credential (JWT) for a space the caller is a member of. The credential is multi-use until it expires and is bound to the caller's DPoP key (cnf.jkt, RFC 9449): it must be presented under the DPoP auth scheme with a per-request proof signed by that key. It is signed by the space authority's signing key so any repo host can verify it without contacting the authority. Identity is resolved from a delegation token when provided (a standalone DPoP proof in the DPoP header supplies the key to bind), otherwise from the DPoP-authenticated user (the session proof key is bound). Membership is checked live against the enrollment store. App-axis (client attestation) gating is enforced here: spaces configured with an app allow-list require a valid client attestation whose attested client_id is listed; spaces that are open ignore any attestation supplied."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
