Skip to content

Contract, Mandate and Signature

Find this scenario in our Bruno collection

Save time in your implementation by observing the sequence of calls and retrieving requests directly from Bruno.

The following documentation describes how to set up, via API, a direct debit mandate linked to a contact, how to display a sale's contract, and how to electronically sign these documents.

Glossary of key concepts

Before going any further, let's make sure we're using the same terminology.

Contact

This is the customer subscribing to the club. To avoid confusion with their potential status (prospect, customer, former customer ...), we will call them contact in this document.

Mandate

The mandate is an authorization to debit the contact's bank account. It links a club that wishes to collect payments to the bank account that will be debited.

Contract

If the sold product is associated with a contract model (product.contractModel is set), a contract is automatically generated with the sale and must be signed.

Macro process and prerequisites

As mentioned earlier, you must know the two main parties involved:

  • the club
  • the contact

Depending on what needs to be signed, the process follows these steps:

  1. Add the mandate — only if a mandate must be created
  2. Display the contract to the user — only if a contract was generated with the sale
  3. Initiate the signature process via SMS
  4. Complete the signature process

Of course, the contact must have a valid mobile phone number to be eligible for electronic signature.

Add the Mandate

POST

/{clientToken}/mandates

WARNING

All fields are required

parameterdescriptionexample
clubIdID of the club in IRI format/{clientToken}/clubs/1
contactIdID of the contact targeted by the mandate. This is an IRI, not just a numeric ID/{clientToken}/contacts/12345
contactFamilyNameContact's last nameDoe
contactGivenNameContact's first nameJohn
contactNumberContact's number423456
contactAddress[addressCountry]CountryFrance
contactAddress[addressCountryIso]PaysFR
contactAddress[addressLocality]CityLa Madeleine
contactAddress[postalCode]Postal code59110
contactAddress[streetAddress]Street address41 rue du Général de Gaulle
holderAccount holderJohn Doe
ibanBank account numberDE15843988385047239833
bicBank identifierDEUTDEFF
bankBank nameDEUTSCHE BANK AG
validFromStart date of mandate validity2019-06-21

Example

POST /{clientToken}/mandates

Body

json5
{
    "clubId": "/{clientToken}/clubs/22",
    "contactId": "/{clientToken}/contacts/1",
    "contactFamilyName": "Doe",  
    "contactGivenName": "John",  
    "contactNumber": "1",  
    "contactAddress": { 
        "addressCountry": "France",
        "addressCountryIso": "FR",
        "addressLocality": "La Madeleine",
        "postalCode": "59110",
        "streetAddress": "41 Rue du Général de Gaulle"
    },
    "holder": "John Doe",
    "iban": "DE15843988385047239833",
    "bic": "DEUTDEFF",
    "bank": "DEUTSCHE BANK AG",
    "validFrom": "2019-06-21"
}

Response 201 Created

json5
{  
   "@context":"\/clientToken\/contexts\/Mandate",
   "@id":"\/clientToken\/mandates\/373969",         // <-- mandate ID
   "@type":"Mandate",
  // ...
}

Display the Contract to the User

If the sold product is associated with a contract model (product.contractModel is set), a contract is automatically generated with the sale and must be signed.

To visually display the contract to the client, simply perform a GET /:clientToken/sales/:saleId/contract, which will return the raw PDF content to display.

curl --location 'https://.../demoapi/sales/12345/contract' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJOdDmWEJwl2Zqc' \
--header 'x-user-club-id: /onfit/clubs/2325' \
--header 'x-user-network-node-id: /onfit/network_nodes/2229' \
--header 'x-gravitee-api-key: xxx-yyy-zzz'

Note

You receive the raw PDF content, so you need to create an endpoint that serves this content with the correct HTTP headers.

Initiate the Signature Process via SMS

The electronic signature process involves sending an SMS to the contact. This SMS contains a code they must use to validate the signature in the next step.

This process is the same for contracts and mandates:

  • If you have only a contract, provide the saleId (/:clientToken/sales/:id) as targetId
  • If you have only a mandate, provide the mandateId (/:clientToken/mandate/:id) as targetId
  • If you have both a contract and a mandate to sign, you can sign both in a single call by providing both IDs in a targetIds array

POST /{clientToken}/signature_requests

parameterdescriptionexample
contactIdContact ID in IRI format/{clientToken}/contacts/1
targetIdID of the mandate to sign in IRI format/{clientToken}/mandates/373969
targetIdsArray of IDs (in IRI format) of items to sign/{clientToken}/mandates/373969

Example

POST /{clientToken}/signature_requests

Body

json5
{
    "contactId": "/{clientToken}/contacts/1",
    // "targetId": "/{clientToken}/mandates/373969"
    "targetIds": [
        "/{clientToken}/mandates/373969",
        "/{clientToken}/sales/936973"
    ]
}

Response 201 Created

json5
{  
   "@context":"\/clientToken\/contexts\/SignatureRequest",
   "@id":"\/clientToken\/signature_requests\/3451",         // <-- signature process ID
   "@type":"SignatureRequest",
  // ...
}

Complete the Signature Process

Once the SMS is received, the application orchestrating the signature must collect the code from the targeted contact and complete the signature process by validating this code.

POST

/{clientToken}/signature_requests/{signatureRequestId}/transitions

parameterdescriptionexample
signatureRequestIdID of the previously created signature process3451
transitionType of transition. Possible values are validate or cancelvalidate
codeValidation code received via SMS1234

Example

POST /{clientToken}/signature_requests/3451/transitions

Body

json5
{
    "transition": "validate",
    "code": "94852"
}

Response 201 Created