---
id: config-digital-wallet-open-id-holder-create-credential-offer
title: "Create credential offer"
description: "Creates an OID4VCI Credential Offer that can be presented to a holder via QR code or deep link. OpenID4VCI 1.0 offers are not yet supported on this operation - the service refuses `version_01` with a 400 - so use `draft_13` until the backend adds 1.0 support. The wallet builds a Credential Offer by value with the Authorization Code Flow. The mandatory fields depend on the version of the OID4VCI specification. Version `draft_13` needs `credentialConfigurationIds`. Version `draft_17` needs `scope`, and does not accept `credentialConfigurationIds`. The offer always uses the Authorization Code Flow with an empty `issuer_state`. This operation does not create a Pre-Authorized Code Flow offer and does not add a `tx_code`."
sidebar_label: "Create credential offer"
hide_title: true
hide_table_of_contents: true
api: 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
sidebar_class_name: "post api-method"
info_path: docs/openid4vc-api/igrant-io-api-documentation
custom_edit_url: null
---

> **Build this with an AI coding agent.** Install the iGrant.io Agent Skills, then ask your agent to build the integration:
>
> ```bash
> npx skills add L3-iGrant/skills
> ```


import ApiTabs from "@theme/ApiTabs";
import DiscriminatorTabs from "@theme/DiscriminatorTabs";
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes";
import MimeTabs from "@theme/MimeTabs";
import ParamsItem from "@theme/ParamsItem";
import ResponseSamples from "@theme/ResponseSamples";
import SchemaItem from "@theme/SchemaItem";
import SchemaTabs from "@theme/SchemaTabs";
import Markdown from "@theme/Markdown";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";

<h1 className={"openapi__heading"}>Create credential offer</h1>

<MethodEndpoint method={"post"} path={"/v2/config/digital-wallet/openid/sdjwt/credential-offer"}></MethodEndpoint>



Creates an OID4VCI Credential Offer that can be presented to a holder via QR code or deep link. OpenID4VCI 1.0 offers are not yet supported on this operation - the service refuses `version_01` with a 400 - so use `draft_13` until the backend adds 1.0 support. The wallet builds a Credential Offer by value with the Authorization Code Flow. The mandatory fields depend on the version of the OID4VCI specification. Version `draft_13` needs `credentialConfigurationIds`. Version `draft_17` needs `scope`, and does not accept `credentialConfigurationIds`. The offer always uses the Authorization Code Flow with an empty `issuer_state`. This operation does not create a Pre-Authorized Code Flow offer and does not add a `tx_code`.

## Request

<MimeTabs className={"openapi-tabs__mime"}><TabItem label={"application/json"} value={"application/json-schema"}><details style={{}} className={"openapi-markdown__details mime"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-mime"}><h3 className={"openapi-markdown__details-summary-header-body"}>Body</h3><strong className={"openapi-schema__required"}>required</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}><div style={{"marginTop":"1rem","marginBottom":"1rem"}}>

Credential issuer and the credentials that the offer must contain.

</div></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"credentialIssuer"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"Credential Issuer Identifier that the offer points to. The holder uses this URL to read the Credential Issuer Metadata.","example":"https://demo-api.igrant.io/v2/organisation/62e29d4c1d75a55b4ecd0e50/service"}}></SchemaItem><SchemaItem collapsible={false} name={"version"} required={false} schemaName={"string"} qualifierMessage={"**Possible values:** [`draft_13`, `draft_17`]"} schema={{"type":"string","description":"Version of the OID4VCI draft specification that the offer follows. The default is `draft_13`. OpenID4VCI 1.0 offers are not yet supported on this operation - the service refuses `version_01` with a 400 - so use `draft_13` until the backend adds 1.0 support.","default":"draft_13","enum":["draft_13","draft_17"],"example":"draft_13"}}></SchemaItem><SchemaItem collapsible={false} name={"credentialConfigurationIds"} required={false} schemaName={"string[]"} qualifierMessage={undefined} schema={{"type":"array","items":{"type":"string","description":"Key of one entry in the `credential_configurations_supported` object of the Credential Issuer Metadata."},"description":"Identifiers of the credential configurations that the offer contains. Use this field with version `draft_13`. Version `draft_17` does not accept this field.","example":["PhotoIdCredential"]}}></SchemaItem><SchemaItem collapsible={false} name={"scope"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"Scope that selects the credential configurations for the offer. Use this field with version `draft_17`. The wallet finds every credential definition of the organisation that has this scope.","example":"photoid"}}></SchemaItem></ul></details></TabItem></MimeTabs><div><div><ApiTabs label={undefined} id={undefined}><TabItem label={"200"} value={"200"}><div>

The wallet created the credential offer.

</div><details style={{"textAlign":"left","marginBottom":"1rem"}} className={"openapi-markdown__details"} data-collaposed={true} open={false}><summary style={{}}><strong>Response Headers</strong></summary><ul style={{"marginLeft":"1rem"}}></ul></details><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"credentialOffer"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"Credential Offer URI that the holder opens. The wallet returns the offer by value in the `credential_offer` query parameter.","example":"openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fdemo-api.igrant.io%2Fv2%2Forganisation%2F62e29d4c1d75a55b4ecd0e50%2Fservice%22%2C%22credential_configuration_ids%22%3A%5B%22PhotoIdCredential%22%5D%2C%22grants%22%3A%7B%22authorization_code%22%3A%7B%22issuer_state%22%3A%22%22%7D%7D%7D"}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"credentialOffer\": \"openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fdemo-api.igrant.io%2Fv2%2Forganisation%2F62e29d4c1d75a55b4ecd0e50%2Fservice%22%2C%22credential_configuration_ids%22%3A%5B%22PhotoIdCredential%22%5D%2C%22grants%22%3A%7B%22authorization_code%22%3A%7B%22issuer_state%22%3A%22%22%7D%7D%7D\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem><TabItem label={"400"} value={"400"}><div>

The organisation is not valid, the version is not supported, or a field that the version needs is missing. Holder operations are also not available for a sandbox organisation.

</div><details style={{"textAlign":"left","marginBottom":"1rem"}} className={"openapi-markdown__details"} data-collaposed={true} open={false}><summary style={{}}><strong>Response Headers</strong></summary><ul style={{"marginLeft":"1rem"}}></ul></details><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"errorCode\": 400,\n  \"errorDescription\": \"Bad input parameter\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem><TabItem label={"401"} value={"401"}><div>

Unauthorized

</div><details style={{"textAlign":"left","marginBottom":"1rem"}} className={"openapi-markdown__details"} data-collaposed={true} open={false}><summary style={{}}><strong>Response Headers</strong></summary><ul style={{"marginLeft":"1rem"}}></ul></details><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"errorCode\": 400,\n  \"errorDescription\": \"Bad input parameter\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem><TabItem label={"500"} value={"500"}><div>

Internal server error

</div><details style={{"textAlign":"left","marginBottom":"1rem"}} className={"openapi-markdown__details"} data-collaposed={true} open={false}><summary style={{}}><strong>Response Headers</strong></summary><ul style={{"marginLeft":"1rem"}}></ul></details><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"errorCode\": 400,\n  \"errorDescription\": \"Bad input parameter\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem></ApiTabs></div></div>
      