# GET /api/stored-credential-consents/{id}

Stored Credential Consents: Gets one consent by its identifier.

Returns what the cardholder agreed to, the exact text they were shown when it was recorded, when and
how the consent was captured, the enrollment terms, the initial transaction, whether it has been
revoked, and the evidence the hosted payment page recorded. Use it to answer an issuer's request for
the cardholder agreement behind a merchant-initiated charge. The `id` is the
`storedCredentialConsentId` a token create returns.

**Operation ID:** `storedCredentialConsentRecordGet`

## Authorization

Requires: StoredCredentialConsents.StoredCredentialConsents, merchant scope.

Requires API key scope: `customers`

Required permissions:
- `StoredCredentialConsents.StoredCredentialConsents`

## Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string(uuid) | The consent identifier. |
| suppressNulls | query | no | boolean | If true, omit properties with null values. |

## Responses

### 200

The consent.

**Content type:** `application/json`

Schema: [`StoredCredentialConsentRecordDto`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/StoredCredentialConsentRecordDto.md)

Properties:
- `id` (string(uuid))
- `customerId` (string(uuid)): The customer who gave the consent. (nullable)
- `paymentMethodId` (string(uuid)): The customer's stored payment method the consent covers. This is the stored payment method's id, not a payment token. (nullable)
- `allowedUsages` ([StoredCredentialUsage](https://devportal.signapay-sbx.winkpg.io/docs/api/models/StoredCredentialUsage.md)): The kinds of later charge the cardholder agreed to (a combination of flags). Values combine: send one or more member names separated by a comma and a space, or the integer sum of their values. Responses carry the names. (nullable)
  Values:
  - `None`: No permitted uses. Consent record is effectively inactive.
  - `Recurring`: Scheduled recurring charges (subscriptions, membership dues). Maps to Recurring.
  - `Installment`: Fixed-schedule installment plans dividing a known total. Maps to Installment.
  - `UnscheduledCOF`: Merchant-triggered charges for pre-agreed events (balance top-ups, usage overages, no-show fees, delayed charges). Maps to several MIT reason codes including UnscheduledCOF, NoShow, DelayedCharge, and IncrementalAuth.
  - `OneTimeFuture`: A single known future cardholder-initiated purchase the credential was saved for (e.g. "save card for my next order"). Not used for MITs.
- `consentTextVersion` (string): The version of the consent text the cardholder was shown: a hash of the rendered text, as returned by the consent configuration operation and sent with the capture. (nullable)
- `consentText` (string): The exact consent text the cardholder was shown. Null when it was not recorded: a consent captured before the text was kept, or one whose text was no longer held when it was captured. The `consentTextVersion` is recorded either way. (nullable)
- `capturedAt` (string(date-time)): UTC time the cardholder gave consent. (nullable)
- `capturedVia` ([ConsentCaptureChannel](https://devportal.signapay-sbx.winkpg.io/docs/api/models/ConsentCaptureChannel.md)): Where the consent was captured: the hosted payment page, the Virtual Terminal, the API, an import or the merchant's back office. (nullable)
  Values:
  - `HostedPaymentPage`: Captured during a hosted payment page checkout via an opt-in checkbox the cardholder ticked. Strongest evidence: cardholder's own action with IP, user agent, and session identifier recorded.
  - `VirtualTerminal`: Captured in the virtual terminal as a merchant operator attestation that consent was obtained from the cardholder offline (in person, by phone, signed form, etc.). Operator identity and capture method recorded.
  - `Api`: Declared by an integrating merchant via the API. The merchant takes liability for the declaration; WinkPG records the API key, timestamp, and merchant-supplied reference.
  - `Imported`: Imported from an external system (e.g. legacy migration, bulk reseller onboarding). Evidence captured outside WinkPG and recorded only as a reference to the external system.
  - `MerchantAdmin`: Captured when a merchant admin manually adds a stored payment method to a customer from the back-office (Customers > customer > Payment Methods). The operator attests that they obtained the cardholder's / account holder's authorization off-line (by phone, in person, or via a signed form on file) and records where the merchant retains that artifact. Operator identity, capture method, ACH authorization type (for bank-account credentials), and a merchant evidence reference are recorded on ConsentEvidence.
- `declaredMethod` (string): How the consent was obtained, for example `OnlineForm` or `Phone`: the method sent with an API capture, or the method an operator recorded in the Virtual Terminal or the back office. Null for a hosted payment page consent, whose evidence is the checkbox the cardholder ticked. (nullable)
- `enrollmentTerms` ([EnrollmentTermsDto](https://devportal.signapay-sbx.winkpg.io/docs/api/models/EnrollmentTermsDto.md)): The terms the cardholder agreed to for a recurring or installment consent: the amount, frequency, duration and any fee, card price or surcharge ceiling stated. Null when none were recorded.
  Fields:
  - `amount` (string): Statement of the amount the cardholder agreed to (for example "$29.99 per month"). (nullable)
  - `frequency` (string): Statement of the charge frequency. (nullable)
  - `duration` (string): Statement of how long the authorization remains in effect. (nullable)
  - `fixedAmount` (number(double)): Fixed per-payment amount the cardholder agreed to, when one was recorded. Carries no currency. (nullable)
  - `amountRangeDescription` (string): Description of the agreed amount range for variable-amount charges. (nullable)
  - `convenienceFee` (string): Statement of the convenience fee the cardholder agreed to pay on every charge. (nullable)
  - `cardPrice` (string): Statement of the dual pricing card price the cardholder agreed to pay on every card charge. (nullable)
  - `surchargeDisclosure` (string): The surcharge ceiling statement the consent text stated. (nullable)
  - `surchargeMaxRate` (number(double)): The surcharge ceiling as a decimal fraction (`0.03` is 3 percent). (nullable)
  - `surchargeNoticeSentAt` (string(date-time)): UTC instant the cardholder was emailed the surcharge notice after enrollment. (nullable)
  - `surchargeEffectiveFrom` (string(date-time)): UTC instant from which a charge under this consent may carry the noticed surcharge. (nullable)
  - `surchargeNoticeUndeliverableAt` (string(date-time)): UTC instant the notice sweep found no way to email the cardholder. (nullable)
  - `surchargeNoticeUndeliverableReason` (string): Short reason code for why the notice could not be sent. Never an address. (nullable)
- `initialTransactionId` (string(uuid)): The transaction during which the consent was captured. Null for a consent captured without one, such as a card stored with no payment. (nullable)
- `initialSchemeTransactionId` (string): The card network's transaction identifier from the initial cardholder-initiated transaction, which later merchant-initiated charges reference. Null when the processor returned none. (nullable)
- `revokedAt` (string(date-time)): UTC time the consent was revoked. Null while it is active. (nullable)
- `isRevoked` (boolean): True when the consent has been revoked and no longer permits a merchant-initiated charge. (read only)
- `evidence` ([ConsentRecordEvidenceDto](https://devportal.signapay-sbx.winkpg.io/docs/api/models/ConsentRecordEvidenceDto.md)): Evidence recorded by the hosted payment page when the cardholder consented there. Null for a consent captured on another channel.
  Fields:
  - `ipAddress` (string): The cardholder's IP address when they consented. (nullable)
  - `userAgent` (string): The cardholder's browser user agent when they consented. (nullable)
  - `hppSessionId` (string): The hosted payment page session in which the cardholder consented. (nullable)
  - `checkboxLabel` (string): The exact label of the checkbox the cardholder ticked. (nullable)
  - `cardConsentMerchantTermsVersion` (string): Version (`sha256:{hex}`) of the merchant's own terms the hosted payment page showed under the card consent text. Null when the page showed no terms, and for a bank account consent. (nullable)
  - `pageDisclosureTextVersion` (string): Version hash (`sha256:{hex}`) of the hosted payment page disclosure text the cardholder accepted on the payment that established this consent. Read-only. `null` when the page did not require acceptance, when the page asked the cardholder to accept a convenience fee disclosure without showing disclosure text of its own, or for a consent captured before acceptance was recorded. (nullable)
  - `pageDisclosureAcceptedAt` (string(date-time)): UTC time the cardholder's acceptance of the hosted payment page disclosure was recorded on the payment that established this consent (server-stamped). Read-only. `null` when the page did not require acceptance, or for a consent captured before acceptance was recorded. (nullable)

### 429

The request was refused because a rate limit was exceeded, or because something a later retry can clear stopped it. A rate limit refusal carries an `application/problem+json` body: wait at least the interval `Retry-After` names before retrying, then back off. Limits are tuned per deployment, so read the allowance from the response headers rather than assuming a fixed ceiling. Any other refusal carries the standard error envelope as `application/json`, and its `error.code` names the cause.

**Content type:** `application/problem+json`

Schema: [`RateLimitProblemDetails`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RateLimitProblemDetails.md)

Properties:
- `type` (string) required: The problem type identifier. Always the same value: the failure is the status code itself, so there is no sub-type for a caller to branch on. (nullable)
- `title` (string) required: A short, human-readable summary of the problem type. (nullable)
- `status` (integer(int32)) required: The HTTP status code, repeated in the body as the problem-details format defines.
- `detail` (string) required: A human-readable explanation of this occurrence of the problem. (nullable)
- `retryAfterSeconds` (integer(int32)) required: How long to wait before retrying, in whole seconds, carrying the same figure as the `Retry-After` header. Always at least one: a value of zero would invite an immediate retry that is certain to be rejected again.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

### 400

Bad request. The request was malformed or failed validation. When validation rejected it, `error.validationErrors` names each member at fault and why.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

_Example: Request failed validation_

One or more fields were rejected before any rule ran. error.code is null on the envelope and the causes are in validationErrors, one entry per failure. An entry carries code when the validator declared a publishable one, and memberPaths when the full path says more than members does (an element inside a collection, for example). Both keys are omitted when they would add nothing.

```json
{
  "error": {
    "code": null,
    "message": "Your request is not valid!",
    "details": "The following errors were detected during validation.",
    "data": {
      "correlationId": "0123456789abcdef0123456789abcdef"
    },
    "validationErrors": [
      {
        "message": "'Amount' must be greater than 0.",
        "members": [
          "amount"
        ]
      },
      {
        "message": "The card has expired.",
        "members": [
          "expirationDate"
        ],
        "code": "CardData:CardExpired"
      },
      {
        "message": "'Value' must not be empty.",
        "members": [
          "value"
        ],
        "memberPaths": [
          "customFields[2].value"
        ]
      }
    ]
  }
}
```

### 401

Unauthorized. The request carried no API key or signed-in session, or the key it carried is invalid, revoked or expired.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

### 403

Forbidden. The API key lacks the scope this operation needs, the signed-in user lacks the permission, or a business rule refused the request. The error code in the body names the reason.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

### 404

No consent with this identifier exists for your merchant.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

_Example: Resource not found_

The id in the path names no record the caller can see. Most resources answer with a null error.code and a message naming the resource type and the id; a resource that publishes a not-found code in the catalog above carries it in error.code instead, so check for one before matching on the message.

```json
{
  "error": {
    "code": null,
    "message": "There is no entity Transaction with id = 7d1f3a52-0c4e-4b8a-9e21-5a6b7c8d9e00!",
    "details": null,
    "data": {
      "correlationId": "0123456789abcdef0123456789abcdef"
    },
    "validationErrors": null
  }
}
```

### 500

Internal server error. The platform failed unexpectedly while handling the request. If it keeps failing, contact support and quote the correlation id, which the response carries in the `X-Correlation-Id` header and as `error.data.correlationId`.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

### 501

Not implemented. The operation is declared but has no implementation on this deployment, so no request to it can succeed. Retrying does not help.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

### default

The request failed. The body carries the standard error envelope: a machine-readable `error.code`, a human-readable `error.message`, and `error.validationErrors` when the failure was a validation rejection. The [error reference](https://devportal.signapay-sbx.winkpg.io/docs/errors.md) lists the values `error.code` can take.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))

_Example: Business rule refused the request_

The request was understood and rejected by a platform rule. This is the shape that carries a code from the catalog above, so branch on error.code rather than on the message text. The HTTP status is the one listed against the code.

```json
{
  "error": {
    "code": "Transactions:OperationNotAllowed",
    "message": "The operation 'Void' is not allowed on a Sale transaction with result 'Approved' and settlement state 'Settled'.",
    "details": null,
    "data": {
      "correlationId": "0123456789abcdef0123456789abcdef"
    },
    "validationErrors": null
  }
}
```

### Errors

These statuses answer with the error envelope outlined below.

- `400`: Bad request. The request was malformed or failed validation. When validation rejected it, `error.validationErrors` names each member at fault and why.
- `401`: Unauthorized. The request carried no API key or signed-in session, or the key it carried is invalid, revoked or expired.
- `403`: Forbidden. The API key lacks the scope this operation needs, the signed-in user lacks the permission, or a business rule refused the request. The error code in the body names the reason.
- `404`: No consent with this identifier exists for your merchant.
- `500`: Internal server error. The platform failed unexpectedly while handling the request. If it keeps failing, contact support and quote the correlation id, which the response carries in the `X-Correlation-Id` header and as `error.data.correlationId`.
- `501`: Not implemented. The operation is declared but has no implementation on this deployment, so no request to it can succeed. Retrying does not help.
- `default`: The request failed. The body carries the standard error envelope: a machine-readable `error.code`, a human-readable `error.message`, and `error.validationErrors` when the failure was a validation rejection. The [error reference](https://devportal.signapay-sbx.winkpg.io/docs/errors.md) lists the values `error.code` can take.

**Content type:** `application/json`

Schema: [`RemoteServiceErrorResponse`](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorResponse.md)

Properties:
- `error` ([RemoteServiceErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceErrorInfo.md))
  Fields:
  - `code` (string): (nullable)
  - `message` (string): (nullable)
  - `details` (string): (nullable)
  - `data` (object): (nullable)
  - `validationErrors` (array<[RemoteServiceValidationErrorInfo](https://devportal.signapay-sbx.winkpg.io/docs/api/models/RemoteServiceValidationErrorInfo.md)>): (nullable)

_Example: Request failed validation_

One or more fields were rejected before any rule ran. error.code is null on the envelope and the causes are in validationErrors, one entry per failure. An entry carries code when the validator declared a publishable one, and memberPaths when the full path says more than members does (an element inside a collection, for example). Both keys are omitted when they would add nothing.

```json
{
  "error": {
    "code": null,
    "message": "Your request is not valid!",
    "details": "The following errors were detected during validation.",
    "data": {
      "correlationId": "0123456789abcdef0123456789abcdef"
    },
    "validationErrors": [
      {
        "message": "'Amount' must be greater than 0.",
        "members": [
          "amount"
        ]
      },
      {
        "message": "The card has expired.",
        "members": [
          "expirationDate"
        ],
        "code": "CardData:CardExpired"
      },
      {
        "message": "'Value' must not be empty.",
        "members": [
          "value"
        ],
        "memberPaths": [
          "customFields[2].value"
        ]
      }
    ]
  }
}
```

## Authentication

- `ApiKey`

## Example request

Every block below sends the same request. Replace {{BASE_URL}} with the address of the API you are calling and {{API_KEY}} with your own key.

### cURL

```bash
curl -X GET "{{BASE_URL}}/api/stored-credential-consents/{id}" \
  -H "api-key: {{API_KEY}}"
```

### PowerShell

```powershell
$headers = @{
    'api-key' = '{{API_KEY}}'
}

$response = Invoke-RestMethod -Method GET -Uri '{{BASE_URL}}/api/stored-credential-consents/{id}' `
    -Headers $headers
```

### TypeScript (SDK)

```bash
npm install @winkpg/winkpg-api
```

```typescript
import { Configuration, StoredCredentialConsentsApi } from '@winkpg/winkpg-api';

const api = new StoredCredentialConsentsApi(new Configuration({
  basePath: '{{BASE_URL}}',
  apiKey: '{{API_KEY}}',
}));

const { data } = await api.storedCredentialConsentRecordGet("3fa85f64-5717-4562-b3fc-2c963f66afa6");
```

### TypeScript (raw HTTP)

```typescript
const response = await fetch('{{BASE_URL}}/api/stored-credential-consents/{id}', {
  method: 'GET',
  headers: {
    "api-key": "{{API_KEY}}",
  },
});

const data = await response.json();
```

### C# (SDK)

```bash
dotnet add package WinkPg.Api.Client
```

```csharp
using WinkPg.Api.Client.Api;
using WinkPg.Api.Client.Client;

var config = new Configuration { BasePath = "{{BASE_URL}}" };
config.AddApiKey("api-key", "{{API_KEY}}");

var api = new StoredCredentialConsentsApi(config);
var result = await api.StoredCredentialConsentRecordGetAsync(Guid.Parse("3fa85f64-5717-4562-b3fc-2c963f66afa6"));
```

### C# (raw HTTP)

```csharp
using var http = new HttpClient { BaseAddress = new Uri("{{BASE_URL}}") };

var request = new HttpRequestMessage(new HttpMethod("GET"), "/api/stored-credential-consents/{id}");
request.Headers.Add("api-key", "{{API_KEY}}");

var response = await http.SendAsync(request);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
```

### Python (SDK)

```bash
pip install winkpg-api
```

```python
import winkpg_api

configuration = winkpg_api.Configuration(host="{{BASE_URL}}")
configuration.api_key["ApiKey"] = "{{API_KEY}}"

with winkpg_api.ApiClient(configuration) as client:
    api = winkpg_api.StoredCredentialConsentsApi(client)
    result = api.stored_credential_consent_record_get("3fa85f64-5717-4562-b3fc-2c963f66afa6")
```

### Python (raw HTTP)

```bash
pip install requests
```

```python
import requests

headers = {
    "api-key": "{{API_KEY}}",
}

response = requests.request(
    "GET",
    "{{BASE_URL}}/api/stored-credential-consents/{id}",
    headers=headers,
)
response.raise_for_status()
data = response.json()
```

## See also

- [All documentation](https://devportal.signapay-sbx.winkpg.io/llms.txt): the machine-readable index of every public page on this site.
