NAV
cURL PHP Ruby Python

Introduction

Welcome to the Mifiel API! We at Mifiel provide a simple and robust RESTful API enabling any service or company operating in Mexico to integrate electronic signatures (using the FIEL) into their workflow.

Through Mifiel’s API, you can easily manage documents and certificates within your Mifiel account.

We have language bindings in Shell, PHP, Ruby and Python! You can view code examples on the right (switch between different programming languages using the tabs on top).

API Versions

All API calls are versioned, and the current Mifiel API is v1.0. We will never introduce any breaking changes within any version, but may add new, non-breaking features and enhancements from time to time.

Sandbox enviroment

For your convenience Mifiel offers a Sandbox environment where you can confidently test your code.

To start using the API in the Sandbox environment you need to first create an account at sandbox.mifiel.com.

Once you have an account you will need an APP_ID and an APP_SECRET which you can generate in sandbox.mifiel.com/access_tokens.

Just change the www.mifiel.com for sandbox.mifiel.com in every endpoint that you use.

Production enviroment

To start using the API in the Production environment you need to first create an account at mifiel.com.

Once you have an account you will need an APP_ID and an APP_SECRET which you can generate in mifiel.com/access_tokens.

Mifiel-supported SDKs

We currently suppport Ruby, PHP and Python but are working on adding more languages.

Ruby

# Configure Mifiel gem
Mifiel.config do |config|
  config.app_id = '<APP_ID>'
  config.app_secret = '<APP_SECRET>'
end

Add this line to your application’s Gemfile:

gem 'mifiel'

Then execute:

$ bundle

Or install it yourself as:

$ gem install mifiel

You can find the repo at github.com/Mifiel/ruby-api-client.

PHP

<?php
// include composer autoload
require 'vendor/autoload.php';

// import Mifiel Client Class
use Mifiel\ApiClient as Mifiel;

// Configure Mifiel Library
Mifiel::setTokens('APP_ID', 'APP_SECRET');
?>

The best way to install Mifiel is quickly and easily with Composer.

To install the most recent version, run the following command.

php composer.phar require mifiel/api-client

Now your composer.json has been updated automatically and you’re able to require the just created vendor/autoload.php file to PSR-4 autoload the library.

You can find the repo at github.com/Mifiel/ruby-api-client.

Python

# Import the Client 
from mifiel import Client

# Configure Mifiel Library, you will 
# pass this to every call you make to our servers.
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
# If you want to make tests without beeing charged
# you can use our sandbox enviroment with:
client.use_sandbox

The best way to install Mifiel lib is with PIP. To install the most recent version please run the following command.

pip install mifiel

You can find the repo at github.com/Mifiel/python-api-client

Authentication

Mifiel uses SHA1 HMAC encryption to authenticate API calls. Each request has to be authenticated by following these steps:

  1. A canonical string is first created using your HTTP headers containing the content-type, content-MD5, request URI and the timestamp. You can replace content-type and content-MD5 with a blank string if needed. The timestamp must be a valid HTTP date. The canonical string is computed as follows:

canonical_string = 'http method,content-type,content-MD5,request URI,timestamp'

  1. This string is then used to create the signature, which is a Base64 encoded SHA1 HMAC, using the APP_SECRET key.

  2. This signature is then added as the Authorization HTTP header in the following form:

Authorization: APIAuth APP-ID:signature-from-step-2

app_id = '<APP_ID>'
app_secret = '<APP_SECRET>'
rest_request = RestClient::Request.new(
  url: 'https://www.mifiel.com/api/v1/documents',
  method: :get,
)
response = ApiAuth.sign!(rest_request, app_id, app_secret).execute
json_response = JSON.load(response)

Ruby Example

If you are using Ruby, we recommend using our official gem.

If you want to create your own, you can use the api-auth gem which supports many popular HTTP clients. In this example we are using the RestClient gem.

Objects

Mifiel data is structured around 3 main types of objects: Document, Certificate and Signature. You’ll find these objects in the format described below.

Document

Contains information about the PDF file being signed

{
  "id": "29f3cb01-744d-4eae-8718-213aec8a1678",
  "original_hash": "e1a580c27d22b4...c537bf90282a6889da",
  "file_file_name": "test-pdf.pdf",
  "signed_by_all": true,
  "signed": true,
  "signed_at": "2016-01-19T16:34:37.921Z",
  "status": [1, "Firmado"],
  "owner": {
    "email": "signer1@email.com",
    "name": "Jorge Morales"
  },
  "callback_url": "https://www.example.com/webhook/url",
  "file": "/api/v1/documents/.../file",
  "file_download": "/api/v1/documents/.../file?download=true",
  "file_signed": "/api/v1/documents/.../file_signed",
  "file_signed_download": "/api/v1/documents/.../file_signed?download=true",
  "file_zipped": "/api/v1/documents/.../zip",
  "signatures": [{
    "email": "signer1@email.com",
    "signed": true,
    "signed_at": "2016-01-19T16:34:37.887Z",
    "certificate_number": "20001000000200001410",
    "tax_id": "AAA010101AAA",
    "signature": "77cd5156779c..4e276ef1056c1de11b7f70bed28",
    "user": {
      "email": "signer1@email.com",
      "name": "Jorge Morales"
    }
  }],
  "widget_id": "ABCD1234"
}

Field Type Description
id String
original_hash String Hash of the original (unsigned) document
file_file_name String Name of the uploaded file
signed_by_all Boolean true if all signers have signed the document
signed_at Date Timestamp of date signed (when all signatures have been collected)
already_signed String[] People that have signed
has_not_signed String[] People that have not signed
status Array [code, code_message] 0: not signed, 1: signed
owner Object The owner of the document. The user who created the document.
callback_url String The callback URL to be POSTed when everybody signs
file String Path where the original document can be downloaded
file_signed String Path where the signed file can be downloaded
file_zipped String Path where the file and signed file in a zip file can be downloaded
signatures Object[] Array of a Signature Model
external_id String A unique id for you to identify the document in the response or fetch it

Endorsable Document

{
  "tracked": true,
  "type": "promissory-note",
  "transferable": true,
  "asset": {
      "id": "f48732f18l67612427c889ae08789032",
      "address": "2N2o6xjB1K5uhjg4Zaj8z9EbnGyrqQazpwX"
  }
}

An endorsable document is a specific type of document whose ownership can be transferred from one person or party to another. Some examples are promissory notes (pagarés), titles (títulos), or invoices (facturas).

You can know if a document is endorsable by checking the tracked parameter. It will be true if a document pertains to this category.

Contains the same information as the Document Model with the following extra attributes:

Field Type Description
tracked boolean Always set to true for endorsable documents.
type String The document type that was specified when the endorsable document was created (currently promissory note is the only supported type)
transferable boolean True if the document is able to be endorsed
asset Object Information about the asset

Asset Object

The asset object has the following attributes

Field Type Description
id String ID of the asset that is assigned to the document
address String The cryptocurrency address that holds the endorsable document

Certificate

Contains information regarding the advanced electronic signatures (e.g. FIEL) used to sign the document

{
  "id": "07320f00-f504-47e0-8ff6-78378d2faca4",
  "type_of": "FIEL",
  "cer_hex": "308204cf30...1303030303030323",
  "owner": "JORGE MORALES MENDEZ",
  "tax_id": "MOMJ811012643",
  "expires_at": "2017-04-28T19:43:23.000Z",
  "expired": false
}
Field Type Description
id String The ID of the Certificate
type_of String Type of certificate used (e.g. FIEL)
owner String Name of the owner as defined in the certificate
tax_id String RFC (tax ID) or other identifier of owner as defined in the certificate
cer_hex String Certificate in hexadecimal
expires_at Date Expiration date of the Certificate
expired Boolean true if the Certificate is expired

Signature

Contains information regarding the signers that have successfully signed the document

{
  "email": "signer1@email.com",
  "signed": true,
  "signed_at": "2016-01-19T16:34:37.887Z",
  "certificate_id": "20001000000200001410",
  "tax_id": "AAA010101AAA",
  "signature": "77cd5156779c..4e276ef1056c1de11b7f70bed28",
  "user": {
    "email": "signer1@email.com",
    "name": "Signer 1"
  }
}
Field Type Description
id String The ID of the Certificate used to sign
email String Email of the signer
signed Boolean true if signed
signed_at Date Timestamp of the date signed
certificate_number String Certificate number assigned by the certificate authority (e.g. SAT)
tax_id String RFC of the signer
signature String Electronic signature on the document (in hexadecimal)

Template

{
  "id": "446e56c9-6df3-444b-ad2b-c582f1fd0dd0",
  "name": "NDA",
  "description": "Confidential disclosure agreement between two parties",
  "has_documents": false,
  "header": "The HTML header",
  "content": "The HTML content",
  "footer": "The HTML footer",
  "csv": "https://www.mifiel.com/api/v1/templates/446e56c9-6df3-444b-ad2b-c582f1fd0dd0/generate_populated_csv"
}
{
  "id": "446e56c9-6df3-444b-ad2b-c582f1fd0dd0",
  "name": "Pagaré",
  "description": "Pagaré between two parties",
  "has_documents": false,
  "header": "The HTML header",
  "content": "The HTML content",
  "footer": "The HTML footer",
  "csv": "https://www.mifiel.com/api/v1/templates/446e56c9-6df3-444b-ad2b-c582f1fd0dd0/generate_populated_csv",
  "tracked": true,
  "type": "promissory-note"
}
Field Type Description
id String The ID of the Template
name String The name of the Template
description String The description
hash_documents Boolean Whether the template has documents or not
header Text The Header of the template
content Text The Content of the template
footer Text The Footer of the template
tracked Boolean Whether the template is used to create endorsable (tracked) documents or non-endorsable documents
type String Type of the template if it is tracked. For now, the only value is ‘promissory-note’ (pagaré)

Signatory

{
  "email": "signatory@email.com",
  "name": "Signatory Name",
  "tax_id": "AAA010101AAA",
  "field": "beneficiary"
}
Field Type Description
email String The email of the signatory
name String Optional The name of the signatory
tax_id String Optional The tax_id (RFC) of the signatory
field String Optional The type of signatory.

The field param is required in endorsable documents. For example in a promissory note document (created with params track: true, type: 'promissory-note') possible values are beneficiary and subscriber for issuing and holder and receiver for transfering.

Documents

Create a Document

Send only original_hash and name if you dont want us to have the document.

require 'mifiel'

document = Mifiel::Document.create(
  track: true, # for endorsable documents only
  type: 'promissory-note', # for endorsable documents only
  file: 'path/to/my-file.pdf',
  signatories: [{ 
    name: 'Signer 1', 
    email: 'signer1@email.com', 
    tax_id: 'AAA010101AAA' 
  }, { 
    name: 'Signer 2', 
    email: 'signer2@email.com', 
    tax_id: 'AAA010102AAA' 
  }],
  callback_url: 'https://www.example.com/webhook/url'
)

# if you dont want us to have the PDF, you can send us 
# the original_hash and the name of the document. Both are required
file_contents = File.read('path/to/my-file.pdf')
original_hash = Digest::SHA256.hexdigest(file_contents)
document = Mifiel::Document.create(
  original_hash: original_hash,
  name: 'my-file.pdf'
  signatories: [ ... ]
)
curl -X POST https://www.mifiel.com/api/v1/documents \
  -F "file=@my-file.pdf" \
  -F "signatories[0][name]=Signer 1" \
  -F "signatories[0][email]=signer@email.com" \
  -F "callback_url=https://www.example.com/webhook/url" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

$document = new Document([
  'file_path' => 'path/to/my-file.pdf',
  'signatories' => [
    [ 
      'name' => 'Signer 1', 
      'email' => 'signer1@email.com', 
      'tax_id' =>  'AAA010101AAA' 
    ],
    [ 
      'name' => 'Signer 2', 
      'email' => 'signer2@email.com', 
      'tax_id' =>  'AAA010102AAA'
    ]
  ]
]);
// if you dont want us to have the PDF, you can just send us 
// the original_hash and the name of the document. Both are required
$document = new Document([
  'original_hash' => hash('sha256', file_get_contents('path/to/my-file.pdf')),
  'name' => 'my-file.pdf',
  'signatories' => ...
]);

$document->save();
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

signatories = [
  { 
    'name': 'Signer 1', 
    'email': 'signer1@email.com', 
    'tax_id': 'AAA010101AAA' 
  },
  { 
    'name': 'Signer 2', 
    'email': 
    'signer2@email.com', 
    'tax_id': 'AAA010102AAA'
  }
]
document = Document.create(
  client=client, 
  signatories=signatories, 
  file='test/fixtures/example.pdf'
)
# if you dont want us to have the PDF, you can just send us 
# the original_hash and the name of the document. Both are required
document = Document.create(
  client=client, 
  signatories=signatories, 
  dhash='some-sha256-hash'
)

Create a document to be signed by passing either a PDF file or the Hash of the file.

If you are using our embedded signing widget, we suggest that you pass a File so that it can be displayed to the end user (signer) within the signing flow on your webpage. Also when using the widget you must pass the email of the signer (name is optional) so that we can send them a copy of the signed document when the signing process is complete.

HTTP Request

POST https://www.mifiel.com/api/v1/documents

Parameters

Field Type Description
file String Optional File to be signed (The hash will be automatically extracted from the file and signed)
original_hash String Optional SHA256 encoded Hash of the original, unsigned document (The hash will be signed)
signatories Array[Signatory] A list of Signatory Object
callback_url String Optional A Callback URL to post when the document gets signed
external_id String Optional A unique id for you to identify the document in the response or fetch it
track Boolean Optional true if you want your document to be andorsable.
type String Optional (Required if param track is true) For now, the only value is ‘promissory-note’ (pagaré)

Response

Returns a Document Model

Get a Specific Document

require 'mifiel'

document = Mifiel::Document.find('29f3cb01-744d-4eae-8718-213aec8a1678')
document.original_hash
document.file
document.file_signed
document.widget_id
# ...
curl "https://www.mfiel.com.mx/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

$document = Document::find('29f3cb01-744d-4eae-8718-213aec8a1678');
$document->original_hash;
$document->file;
$document->file_signed;
# ...
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

document = Document.find(client, 'id')
document.original_hash
document.file
document.file_signed
# ...

Allows you to retrieve a specific document.

HTTP Request

GET https://www.mifiel.com/api/v1/documents/:id

Response

Returns a Document Models

Get All Documents

require 'mifiel'

documents = Mifiel::Document.all
curl "https://www.mifiel.com/api/v1/documents"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

$documents = Document::all();
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

documents = Document.all(client)

Allows you to retrieve all documents in your account.

HTTP Request

GET https://www.mifiel.com/api/v1/documents

Response

Returns an Array of Document Model

Delete a Document

require 'mifiel'

Mifiel::Document.delete('29f3cb01-744d-4eae-8718-213aec8a1678')
curl -X DELETE "https://www.mifiel.com/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

Document::delete('29f3cb01-744d-4eae-8718-213aec8a1678');
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

Document.delete(client, '29f3cb01-744d-4eae-8718-213aec8a1678')

Allows you to delete a specific document in your account.

HTTP Request

DELETE https://www.mifiel.com/api/v1/documents/:id

Request signature

Sends an email request for the document to be signed.

require 'mifiel'

document = Mifiel::Document.find('29f3cb01-744d-4eae-8718-213aec8a1678')
email = 'signer@email.com'
cc = ['signer@email.com', 'viewer@email.com']
document.request_signature(email, cc: cc)
curl -X POST "https://www.mifiel.com/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678/request_signature" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

email = 'signer@email.com'
cc = ['signer@email.com', 'viewer@email.com']
document = Document.find(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
document.request_signature(email, cc=cc)

Response from Mifiel:

  {
    "status": "success",
    "message": "Correo enviado",
    "data": {
      "document": {
        "id": "29f3cb01-744d-4eae-8718-213aec8a1678"        
      }
    }
  }

HTTP Request

POST https://www.mifiel.com/api/v1/documents/:id/request_signature

Parameters

Field Type Description
email String Email of the signer
cc String Email of any non-signing viewers that should receive a copy of the signed document

Transfer a document

require 'mifiel'

document = Mifiel::Document.find('29f3cb01-744d-4eae-8718-213aec8a1678')

# For promissory-note the call is very simple
document.transfer(
  callback_url: 'https://www.example.com/webhook/url',
  receiver: 'receiver@email.com', # simple
  receiver: { # if you want to ensure that the receiver has a specific tax_id (RFC)
    name: 'Receiver',
    email: 'receiver@email.com',
    tax_id: 'AAA010102AAA'
  }
)

# Or for a specific endorsable document type
document.transfer(
  file: 'path/to/my-transfer-file.pdf', # required in certain endorsable document types
  callback_url: 'https://www.example.com/webhook/url',
  signatories: [{
    name: 'Issuer',
    email: 'issuer@email.com',
    tax_id: 'AAA010101AAA',
    field: 'issuer' # Could change depending on the endorsable document type
  }, {
    name: 'Receiver',
    email: 'receiver@email.com',
    tax_id: 'AAA010102AAA',
    field: 'receiver' # Could change depending on the endorsable document type
  }]
)

# Transfer using a template
document.transfer(
  ...
  template_id: '29f3cb01-744d-4eae-8718-213aec8a1678',
  fields: {
    name: 'My Client Name',
    date: '27 Sep 2017'
  }
  ...
)
curl -X POST https://www.mifiel.com/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678/transfer \
  -F "file=@my-file.pdf" \
  -F "signatories[0][name]=Issuer" \
  -F "signatories[0][email]=issuer@email.com" \
  -F "signatories[0][field]=issuer" \
  -F "signatories[1][name]=Receiver" \
  -F "signatories[1][email]=receiver@email.com" \
  -F "signatories[1][field]=receiver" \
  -F "callback_url=https://www.example.com/webhook/url" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

$document = Document::find('29f3cb01-744d-4eae-8718-213aec8a1678');
# For promissory-note the call is very simple
$document->transfer([
  'callback_url': 'https://www.example.com/webhook/url',
  'receiver': 'receiver@email.com', # simple
  'receiver': [ # if you want to ensure that the receiver has a specific tax_id (RFC)
    'name': 'Receiver',
    'email': 'receiver@email.com',
    'tax_id': 'AAA010102AAA'
  ]
])

# Or for a specific endorsable document type
$document.transfer(
  'file': 'path/to/my-transfer-file.pdf', # required in certain endorsable document types
  'callback_url': 'https://www.example.com/webhook/url',
  'signatories': [[
    'name': 'Issuer',
    'email': 'issuer@email.com',
    'tax_id': 'AAA010101AAA',
    'field': 'issuer' # Could change depending on the endorsable document type
  ], [
    'name': 'Receiver',
    'email': 'receiver@email.com',
    'tax_id': 'AAA010102AAA',
    'field': 'receiver' # Could change depending on the endorsable document type
  ]]
)

# Transfer using a template
$document.transfer([
  # ...
  'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
  'fields': [
    'name': 'My Client Name',
    'date': '27 Sep 2017'
  ]
  # ...
])
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

document = Document.find(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
# For promissory-note the call is very simple
document.transfer(
  'callback_url': 'https://www.example.com/webhook/url',
  'receiver': 'receiver@email.com', # simple
  'receiver': { # if you want to ensure that the receiver has a specific tax_id (RFC)
    'name': 'Receiver',
    'email': 'receiver@email.com',
    'tax_id': 'AAA010102AAA'
  }
)

# Or for a specific endorsable document type
document.transfer(
  'file': 'path/to/my-transfer-file.pdf', # required in certain endorsable document types
  'callback_url': 'https://www.example.com/webhook/url',
  'signatories': [{
    'name': 'Issuer',
    'email': 'issuer@email.com',
    'tax_id': 'AAA010101AAA',
    'field': 'issuer' # Could change depending on the endorsable document type
  }, {
    'name': 'Receiver',
    'email': 'receiver@email.com',
    'tax_id': 'AAA010102AAA',
    'field': 'receiver' # Could change depending on the endorsable document type
  }]
)

# Transfer using a template
document.transfer(
  # ...
  'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
  'fields': {
    'name': 'My Client Name',
    'date': '27 Sep 2017'
  }
  # ...
)

Endorsable documents (created with track: true param) can be transferred to other users. To do this, the receiver must have an account in Mifiel and must have set up their account to be able to receive endorsable documents.

A transfer document is a page that is annexed to the original document that contains the terms of the agreement to endorse the document. It is signed by the owner (as well as the receiver in some cases) to acknowledge that the ownership of the document has been transferred. Mifiel generates a transfer document by default at the time of endorsement, but if you would like to use your own custom text and design, please contact us.

In the case that the receiver account is not configured, we will return an error and send an email requiring him to do so. When the receiver configures his account we will send a notification to the callback_url provided so your system knows when to retry the call again.

Use this endpoint to transfer an endorsable document.

HTTP Request

POST https://www.mifiel.com/api/v1/documents/:id/transfer

Parameters

Field Type Description
callback_url String Optional A Callback URL to post when the document gets signed
receiver String(email) OR Hash Optional Receiver info, it could be an email or a hash containing name, tax_id (RFC) and email.
file File Optional The Transfer File. Depending on the endorsable document type, it could be required.
signatories Array[Signatory] Optional A list of Signatory Object
template_id String Optional The template id that you want to use to create the File.
fields JSON [Hash] Optional A hash with the fields {name: value}

Response

Returns a Tracked Document Model

Certificates

At the moment we only support signing with the FIEL (the most frequently used advanced electronic signature in Mexico). We will soon be adding support for additional types of electronic signatures and will update the documentation as we do so.

Create a Certificate

require 'mifiel'

certificate = Mifiel::Certificate.create(
  file: 'path/to/my-certificate.cer'
)
curl -X POST https://www.mifiel.com/api/v1/keys \
  -F "file=@my-certificate.cer" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;

$certificate = new Certificate([
  'file' => 'path/to/my-certificate.cer'
])
$certificate->save();
?>

Uploads the certificate of a signer in your account.

HTTP Request

POST https://www.mifiel.com/api/v1/keys

Parameters

Field Type Description
file String .cer File of your FIEL

Response

Returns a Certificate Model

Get a Specific Certificate

require 'mifiel'

certificate = Mifiel::Certificate.find('07320f00-f504-47e0-8ff6-78378d2faca4')
certificate.type_of
certificate.owner
certificate.tax_id
# ...
curl "https://www.mfiel.com.mx/api/v1/keys/07320f00-f504-47e0-8ff6-78378d2faca4"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;

$certificate = Certificate::find('07320f00-f504-47e0-8ff6-78378d2faca4');
$certificate->cer_hex;
$certificate->type_of;
$certificate->owner;
# ...
?>

Allows you to retrieve a specific certificate.

HTTP Request

GET https://www.mifiel.com/api/v1/keys/:id

Response

Returns a Certificate Model

Get All Certificates

require 'mifiel'

certificates = Mifiel::Certificate.all
curl "https://www.mifiel.com/api/v1/keys"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;

$certificates = Certificate::all();
?>

Allows you to retrieve ALL certificates in your account.

HTTP Request

GET https://www.mifiel.com/api/v1/keys

Response

Returns an Array of a Certificate Model

Delete a Certificate

require 'mifiel'

Mifiel::Certificate.delete('07320f00-f504-47e0-8ff6-78378d2faca4')
curl -X DELETE "https://www.mifiel.com/api/v1/keys/07320f00-f504-47e0-8ff6-78378d2faca4"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;

Certificate::delete('id');
?>

Allows you to delete a specific certificate in your account.

HTTP Request

DELETE https://www.mifiel.com/api/v1/keys/:id

Templates

Create a Template

require 'mifiel'

content = '<div>' \
            'Name <field name="name" type="text">NAME</field>' \
            'Date <field name="date" type="text">DATE</field>' \
          '</div>'

template = Mifiel::Template.create(
  name: 'my-company-nda', 
  description: 'Confidential disclosure agreement',
  header: '<div>some header html</div>', 
  content: content, 
  footer: '<div>some footer html</div>'
)
curl -X POST https://www.mifiel.com/api/v1/templates \
  -F "name=my-company-nda" \
  -F "description=Confidential disclosure agreement" \
  -F "content=<div>html content</div>" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;

$content = '<div>' .
             'Name <field name="name" type="text">NAME</field>' .
             'Date <field name="date" type="text">DATE</field>' .
           '</div>'

$template = new Template([
  'name' => 'my-company-nda', 
  'description' => 'Confidential disclosure agreement',
  'header' => '<div>some header html</div>', 
  'content' => $content, 
  'footer' => '<div>some footer html</div>'
]);
$template->save();
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

content = '<div>' +
             'Name <field name="name" type="text">NAME</field>' +
             'Date <field name="date" type="text">DATE</field>' +
           '</div>'
template = Template.create(
  client=client,
  name='my-company-nda', 
  description='Confidential disclosure agreement',
  header='<div>some header html</div>', 
  content=content, 
  footer='<div>some footer html</div>'
)

Templates are a tool that allows you to create templates that have a base format. You can define fields within the html so you can then create a custumized document.

HTTP Request

POST https://www.mifiel.com/api/v1/templates

Parameters

Field Type Description
track Boolean Optional true if you want documents generated from this template to be endorsable
type String Optional (Required if param track is true) For now, the only value is 'promissory-note’ (pagaré)
name String The name of the template
description String Optional Internal description of your template
header Text/HTML Optional The Header of the PDF
content Text/HTML The Content of the PDF
footer Text/HTML Optional The footer of the PDF

Response

Returns a Template Model

Get a Specific Template

require 'mifiel'

template = Mifiel::Template.find('29f3cb01-744d-4eae-8718-213aec8a1678')
template.name
template.header
template.content
# ...
curl "https://www.mfiel.com.mx/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;

$template = Template::find('29f3cb01-744d-4eae-8718-213aec8a1678');
$template->name;
$template->header;
$template->content;
# ...
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

template = Template.find(client, 'id')
template.name
template.header
template.content
# ...

Allows you to retrieve a specific template.

HTTP Request

GET https://www.mifiel.com/api/v1/templates/:id

Response

Returns a Template Model

Get All Templates

require 'mifiel'

templates = Mifiel::Template.all
curl "https://www.mifiel.com/api/v1/templates"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;

$templates = Template::all();
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

templates = Template.all(client)

Allows you to retrieve all templates in your account.

HTTP Request

GET https://www.mifiel.com/api/v1/templates

Response

Returns an Array of Template Models

Delete a Template

require 'mifiel'

Mifiel::Template.delete('29f3cb01-744d-4eae-8718-213aec8a1678')
curl -X DELETE "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678"
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;

Template::delete('29f3cb01-744d-4eae-8718-213aec8a1678');
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

Template.delete(client, '29f3cb01-744d-4eae-8718-213aec8a1678')

Allows you to delete a specific template in your account.

HTTP Request

DELETE https://www.mifiel.com/api/v1/templates/:id

Template fields

Get the fields of a specific template. Use it to know what to send to generate documents with this template.

require 'mifiel'

fields = Mifiel::Template.fields('29f3cb01-744d-4eae-8718-213aec8a1678')
curl "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678/fields" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;

Template::fields('29f3cb01-744d-4eae-8718-213aec8a1678');
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

fields = Template.fields(client, '29f3cb01-744d-4eae-8718-213aec8a1678')

Response from Mifiel:

[{
  "type": "text", 
  "name": "name",
  "value": "Miguel Rodriguez" 
}, {
  "type": "text", 
  "name": "date",
  "value": "15/8/2018"
}]

HTTP Request

GET https://www.mifiel.com/api/v1/templates/:id/fields

Response

Returns an array of the template fields (parsed from the HTML) where each field has the following information:

Field Type Description
type String HTML type attribute of the field
name String HTML name attribute of the field
value String Value which was placed between the field tag in the HTML

Template documents

Get all the active (non deleted) documents generated from a specific template.

require 'mifiel'

documents = Mifiel::Template.documents('29f3cb01-744d-4eae-8718-213aec8a1678')
document = documents.first
# Mifiel::Document
document.id
# "abcd1234"
document.status
# [0, "Pending"]
curl "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678/documents" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

documents = Template.documents(client, '29f3cb01-744d-4eae-8718-213aec8a1678')

Response from Mifiel:

[{
  "id": "document-id",
  "file_name": "file-name.pdf",
  "status": [0, "Pending"],
  "owner": {
    "email": "signer1@email.com",
    "name": "Jorge Morales"
  },
  "file": "/api/v1/documents/.../file"
}]

HTTP Request

GET https://www.mifiel.com/api/v1/templates/:id/documents

Response

Returns an array with the following information about each document:

Field Type Description
id String ID of the document
file_name String Name of the template file created
status Array [code, code_message] 0: not signed, 1: signed
owner Object The owner of the document. The user who created the document.
file String Path where the original document can be downloaded

Generate a document from a template

require 'mifiel'

document = Mifiel::Document.create_from_template(
  template_id: '29f3cb01-744d-4eae-8718-213aec8a1678', 
  name: 'document.pdf',
  fields: {
    name: 'My Client Name',
    date: 'Sep 27 2017'
  },
  signatories: [{
    name: 'Some name',
    email: 'some@email.com',
    tax_id: 'AAA010101AAA'
  }],
  callback_url: 'https://www.example.com/webhook/url',
  external_id: 'unique-id'
)

# If you already have a Template instance you can also do
document = template.generate_document(
  name: 'document.pdf',
  fields: { ... },
  ...
)

# document.id
# document.original_hash
# document.signers
curl -X POST "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678/generate_document" \
  -F "namme='My Client Name'" \
  -F "fields[name]=My Client Name" \
  -F "fields[date]=Sep 27 2017" \
  -F "signatories[0][name]=Some name" \
  -F "signatories[0][email]=some@email.com" \
  -F "signatories[0][tax_id]=AAA010101AAA" \
  -H "Authorization: APIAuth APP-ID:hmac-signature"
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

args = {
  'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
  'name': 'My NDA',
  'fields': {
    'name': 'My Client Name',
    'date': 'Sep 27 2017'
  },
  'signatories': [{
    'name': 'Some name',
    'email': 'some@email.com',
    'tax_id': 'AAA010101AAA'
  }],
  'callback_url': 'https://www.example.com/webhook/url',
  'external_id': 'unique-id'
}
document = Document.create_from_template(client, args)
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

$args = [
  'template_id' => '29f3cb01-744d-4eae-8718-213aec8a1678',
  'name' => 'My NDA',
  'fields' => [
    'name' => 'My Client Name',
    'date' => 'Sep 27 2017'
  ],
  'signatories' => [[
    'name' => 'Some name',
    'email' => 'some@email.com',
    'tax_id' => 'AAA010101AAA'
  ]],
  'callback_url' => 'https://www.example.com/webhook/url',
  'external_id' => 'unique-id'
]

$document = Document.create_document($args)
?>

HTTP Request

POST https://www.mifiel.com/api/v1/templates/:id/generate_document

Parameters

Field Type Description
track Boolean Optional true if you want your document to be endorsable
type String Optional (Required if param track is true) For now, the only value is 'promissory-note’ (pagaré)
name String Optional The name of the document
fields JSON [Hash] A hash with the fields {name: value}
signatories Array[Signatory] A list of Signatory Object
callback_url String Optional A Callback URL to post when the document gets signed
external_id String Optional A unique id for you to identify the document in the response or fetch it

Response

Returns a Document Model

Generate several documents from a template

require 'mifiel'

args = {
  template_id: '29f3cb01-744d-4eae-8718-213aec8a1678',
  identifier: 'name',
  callback_url: 'https://www.my-site.com/documents-ready',
  documents: [{
    fields: {
      name: 'My Client Name',
      date: 'Sep 27 2017'
    },
    signatories: [{
      name: 'Some Name',
      email: 'some@email.com',
      tax_id: 'AAA010101AAA'
    }],
    callback_url: 'https://www.my-site.com/sign-webhook',
    external_id: 'unique-id'
  }]
}
response = Mifiel::Document.create_many_from_template(args)
response.status == 'success'
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')

args = {
  'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
  'identifier': 'name',
  'callback_url': 'https://www.my-site.com/documents-ready',
  'documents': [{
    'fields': {
      'name': 'My Client Name',
      'date': 'Sep 27 2017'
    },
    'signatories': [{
      'name': 'Some Name',
      'email': 'some@email.com',
      'tax_id': 'AAA010101AAA'
    }],
    'callback_url': 'https://www.my-site.com/sign-webhook',
    'external_id': 'unique-id'
  }]
}
documents = Document.create_many_from_template(client, template_id, identifier, docs)
<?php
require 'vendor/autoload.php';
use Mifiel\Document;

$args = [
  'template_id' => '29f3cb01-744d-4eae-8718-213aec8a1678',
  'identifier' => 'name',
  'callback_url' => 'https://www.my-site.com/documents-ready',
  'documents' => [{
    'fields' => {
      'name' => 'My Client Name',
      'date' => 'Sep 27 2017'
    },
    'signatories' => [{
      'name' => 'Some Name',
      'email' => 'some@email.com',
      'tax_id' => 'AAA010101AAA'
    }],
    'callback_url' => 'https://www.my-site.com/sign-webhook',
    'external_id' => 'unique-id'
  }]
]
$documents = Document.create_many_from_template($args)
?>

The generation of documents runs in the background. We will respond with 200 (OK) and start generating the documents. When our servers finish, we will POST you to the provided callback_url with a list of the created documents.

HTTP Request

POST https://www.mifiel.com/api/v1/templates/:id/generate_documents

Response from Mifiel:

{ "status": "success" }

When the documents are ready, we will send you a POST to the callback_url with the following params:

[{
  "id": "d6793b57-9101-4ce3-ae0d-e51868f3fdf9",
  "folio": "{asset_id}|{address}",
  "signers": [{
    "name": "Some Name",
    "email": "some@email.com",
    "tax_id": "AAA010101AAA",
    "widget_id": "d6793b57-9101-4ce3-ae0d-e51868f3fdf9"
  }],
  "file_name": "NDA-My-Client-Name.pdf",
  "callback_url": "https://www.my-site.com/webhook",
  "external_id": "unique-id"
}]

Parameters

Field Type Description
identifier String Optional A field name to use in the document name e.g “name” will append the field “name” to the document name “My-NDA-My-Client-Name.pdf”
callback_url String A Callback URL to POST when all documents have been created
documents Array[Document] Array of documents to create

Documents Param

Field Type Description
name Hash The name of the document eg. document.pdf
fields Hash Hash of key, value of each field
{field_name: 'Field Content'}
signatories Array[Signatory] A list of Signatory Object
callback_url String Optional A Callback URL to post when the document gets signed
external_id String Optional A unique id for you to identify the document in the response or fetch it

Embedded Signing

Widget

Copy this code and paste it just before the </body> tag.

<script type="text/javascript">
  window.mifiel=window.mifiel||[],function(){"use strict";for(var e=["widget"],i=function(e){return function(){window.mifiel.push([e].concat(Array.prototype.slice.call(arguments,0)))}},t=0;t<e.length;t++){var n=e[t];window.mifiel[n]||(window.mifiel[n]=i(n))}if(!document.getElementById("mifiel-js")){var r=document.createElement("script"),o=document.getElementsByTagName("script")[0];r.type="text/javascript",r.id="mifiel-js",r.async=!0,r.src="https://www.mifiel.com/sign-widget-v1.0.0.js",o.parentNode.insertBefore(r,o)}}();
</script>

Then insert the widget in the desired view (page) by including the following snippet:

<script type="text/javascript">
  window.mifiel.widget({
    widgetId: 'c8aa73d1-db06-4d18-9f56-196b00f6eb69',
    appendTo: 'id-of-the-element-to-append',
    successBtnText: 'Proceed to next step'
  });
</script>

The widget is an embedded signing tool that we have created to allow your users to sign documents in an iFrame within your page. By embedding this tool, your users can sign seamlessly without having to leave the flow of your website.

Note: The signers do not have to have an account in mifiel.com

To begin, you have to copy and paste our code snippet (shown to your right) into the code of the page where the signing flow will take place.

You can also find the code snippet here.

Options

Field Type Default Description
widgetId String Widget ID. You can get it with document.widget_id in Ruby
appendTo String body ID of the element in the page
successBtnText String ‘OK’ Text of the button at the end of the signing flow. When the user click
pdf Base64 null Optional PDF in Base64 if you did not send us the PDF when you created the document.
color String 37BC9B Optional Custom color in hexadecimal (e.g. 555555) to personalize the look and feel of your widget. Typically the primary color of your app.
width String 100% Optional Width of the widget [px or %]
height String 1100 Optional Height of the widget [px]

Events

Listen for Mifiel events:

<script type="text/javascript">
window.addEventListener('message', function (e) {
  console.log(e);
  // accept messages from known hosts only
  // change to https://stageex.mifiel.com if necessary
  if (e.origin !== 'https://www.mifiel.com') {
    return;
  }
  // We will always send an object
  if (typeof e.data !== 'object') {
    return;
  }
  // document signed succesfully
  if (e.data.eventType === 'mifiel.widget.success') {
    var data = e.data,
        doc = data.document,
        signature = data.signature;
    // doc.original_hash;
    // doc.file_signed;
  }
  // Event errors
  if (e.data.eventType === 'mifiel.widget.error') {
    var error = e.data.error;
    // error.code => 1001
    // error.message => 'Invalid PDF, the pdf param has no data'
  }
}, false);
</script>

We will send a postMessage to your page to notify any of the events listed below.

In order to secure the events sent by the widget you must verify that the event is coming from our servers.

You can identify the events by e.data.eventType. The success event will have “mifiel.widget.success” and the error events will have “mifiel.widget.error”.

Success event

We will send the document json object and the signature of the user.

Error events

Error events have the property eventType set as “mifiel.widget.error” and a error object (e.data.error) with code and message properties:

Widget setup error events

Event Code Message
Empty PDF 1001 Invalid PDF, the pdf param has no data
Hashes do not match 1002 Invalid PDF, the provided pdf param is not the same as the uploaded one

Note: We send this errors only when you did not send us the PDF when the document was created.

User error events

Event Code Message
Invalid Certificate 2001 Certificate is not valid
Invalid Private Key 2002 Invalid Private Key
Invalid Pasword 2003 Invalid password
Files do not match 2004 .key file does not belong to the .cer file

Server error events

Event Code Message
Signature failure 3002 Fail to sign document

Embedded Signing Flow

Following is a more detailed explanation of the steps involved in requesting and executing signatures within the embedded signing widget.

  1. The first step is to create a Document in your backend with the API_ID and APP_SECRET. You must pass the PDF file that is being signed (or a SHA256 encoded hash of the PDF and the name of the file), along with the following parameters: webhook (callback_url) and the email and name (optional) of each signer.

  2. Mifiel will return a Widget ID in the response, which you will then need to pass to the widget (running on your website’s front-end).

  3. The signature process then takes place within your website. The signer will be able to preview the document, select the files of their FIEL, and enter the password of their FIEL to sign (during this process Mifiel will be verifying that the FIEL is valid and not expired).

  4. If successful, the signer will be presented with a page explaining that the signing was successful and that they will receive an email with the signed document. We will also display a confirmation button (e.g. 'Proceed to next step’) which will return the user to the flow of your website.

  5. Mifiel will then POST the document information to the webhook specified by you (in Step 1): electronic signature of the document, timestamp of signature, the signature page, and information regarding the public certificate(s) used to sign the document.

Endorsables setup

User account setup

Every user (issuer or receiver) of an endorsable document must set up his account. During this setup process, we will use the user’s FIEL/e.firma to derive a set of cryptocurrency addresses where the assets (the endorsable documents) will be stored.

The widget is an embedded tool to setup the required private keys that generate the addresses. By embedding this tool, your users can setup their account without having to leave the flow of your website.

The flow to embed this tool into your site is: 1. Create a Setup widget_id on our server for your user. 2. Save the widget_id in your database so you can access it later. 3. Use the widget_id in the setup-snippet. An iframe will be placed within your site where your user would drag his FIEL and a backup certificate. 4. When the setup is complete, the iframe will trigger an event so you can redirect the user to the next step in your flow.

Require a setup widget id

HTTP Request

POST https://www.mifiel.com/api/v1/users/setup-widget

Parameters

Field Type Description
email String Email of the user
tax_id String Optional Tax Id (RFC) of the user
callback_url String Optional URL where we will POST when the user completes the process

Response

Field Type Description
widget_id String Widget Id to be used on the snippet

User account setup widget

Options

Field Type Default Description
widgetId String Widget ID.
appendTo String body ID of the element in the page
successBtnText String ‘OK’ Text of the button at the end of the setup flow. When the user clicks, will trigger an event so you can cach it.
color String 37BC9B Optional Custom color in hexadecimal (e.g. 555555) to personalize the look and feel of your widget. Typically the primary color of your app.
width String 100% Optional Width of the widget [px or %]
height String 1100 Optional Height of the widget [px]

Events

Listen for Mifiel events:

<script type="text/javascript">
window.addEventListener('message', function (e) {
  console.log(e);
  // accept messages from known hosts only
  // change to https://app-stageex.mifiel.com if necessary
  if (e.origin !== 'https://app.mifiel.com') {
    return;
  }
  // We will always send an object
  if (typeof e.data !== 'object') {
    return;
  }
  // setup completed
  if (e.data.eventType === 'mifiel.setup-widget.success') {
    var data = e.data,
        doc = data.document
  }
  // Event errors
  if (e.data.eventType === 'mifiel.setup-widget.error') {
    var error = e.data.error;
    // error.code
    // error.message
  }
}, false);
</script>

We will send a postMessage to your page to notify any of the events listed below.

In order to secure the events sent by the widget you must verify that the event is coming from our servers.

You can identify the events by e.data.eventType. The success event will have “mifiel.setup-widget.success” and the error events will have “mifiel.setup-widget.error”.

Success event

We will send the document json object and the signature of the user.

Error events

Error events have the property eventType set as “mifiel.setup-widget.error” and a error object (e.data.error) with code and message properties:

User error events

Event Code Message
Invalid Certificate 2001 Certificate is not valid
Invalid Private Key 2002 Invalid Private Key
Invalid Pasword 2003 Invalid password
Files do not match 2004 .key file does not belong to the .cer file

Server error events

Event Code Message
Setup failure 3002 Fail to setup user

Errors

Error codes

Mifiel API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request had an error. (more info in the errors response param)
401 Unauthorized – Your authorization header is wrong.
402 Payment Required – Your request requires a paid plan. If you already have a plan, it may have expired.
404 Not Found – The specified object could not be found.
405 Method Not Allowed – You tried to access an invalid method.
406 Not Acceptable – You requested a format that isn’t supported.
410 Gone – The requested object has been removed from our servers.
422 Unprocessable Entity – Something happened when we tried to save your request.
429 Too Many Requests – You’re making too many requests! Slow down!
500 Internal Server Error – We had a problem in our servers. Please try again later.
503 Service Unavailable – We’re temporarily offline for maintenance. Please try again later.

Error Handling

All errors follow the JSend specification. Following are examples of error objects found in the body of error responses (e.g. non-200 status code).

When a client sends an unexpected request:

JSON Example fail response:

  {
    "status": "fail",
    "errors": [
      "Document#29f3cb01-744d-4eae-8718-213aec8a1678 not found"
    ]
  }
Field Type Description
status String fail
errors Array Array of error messages

For server errors:

JSON Example error response:

  {
    "status": "error",
    "message": "500: Internal Server Error" 
  }
Field Type Description
status String error
message String A descriptive message